10 个技巧和窍门助你成为更优秀的 ReactJS 开发者
介绍
好了,伙计们,是时候再写一篇文章来为您提供一些您可以立即用来改进 React 游戏的知识,以帮助您成为更好的 React 开发人员,编写更好的代码或在编码面试中表现出色。
在函数组件中使用 React Hooks
React v16.8 引入了 Hooks,这极大地提升了 React 中的函数式编程能力。有了 Hooks,你现在可以、也应该使用函数式组件来替代类组件了。但是等等……函数式组件和状态?还有生命周期方法呢?
别担心 - React Hooks 已经为你做好了准备。让我们来看一些例子:
class myComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '',
};
}
onChange = event => {
this.setState({ value: event.target.value });
};
render() {
return (
<div>
<h1>This is a random class component</h1>
<input
value={this.state.value}
type="text"
onChange={this.onChange}
/>
<p>{this.state.value}</p>
</div>
);
}
}
这是使用类的传统方法。但是有了 Hook,我们现在可以使用 useState Hook 来实现:
const myComponent = () => {
const [value, setValue] = React.useState('');
const onChange = event => setValue(event.target.value);
return (
<div>
<h1>This is a random functional component with state!</h1>
<input value={value} type="text" onChange={onChange} />
<p>{value}</p>
</div>
);
};
看起来简单多了?确实如此!我们使用 useState Hook 将初始状态设置为空字符串 (''),它返回一个包含当前状态 (value) 的数组,并返回一个修改该状态的方法 (setValue)。我们还使用数组解构来访问 [value, setValue]。
默认情况下,函数式组件无法访问生命周期方法。但现在我们有了 hooks,useEffect Hook 可以帮我们解决这个问题。首先是使用类的传统方法:
class myComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
value: localStorage.getItem('someRandomValue') || '',
};
}
componentDidUpdate() {
localStorage.setItem('someRandomValue', this.state.value);
}
onChange = event => {
this.setState({ value: event.target.value });
};
render() {
return (
<div>
<h1>Just some random class component!</h1>
<input
value={this.state.value}
type="text"
onChange={this.onChange}
/>
<p>{this.state.value}</p>
</div>
);
}
}
以下是使用 useEffect Hook 的相同示例:
const myComponent = () => {
const [value, setValue] = React.useState(
localStorage.getItem('someRandomValue') || '',
);
React.useEffect(() => {
localStorage.setItem('someRandomValue', value);
}, [value]);
const onChange = event => setValue(event.target.value);
return (
<div>
<h1>Some random functional component with state and side Effects!</h1>
<input value={value} type="text" onChange={onChange} />
<p>{value}</p>
</div>
);
};
这有多棒?当传递的数组 [value] 中的一个值发生变化时,useEffect 就会运行。
这只是使用 React Hooks 的两个示例。还有很多其他的 Hooks,你甚至可以创建自己的自定义 Hooks。我认为每个 ReactJS 开发者都应该学习这个概念!
使用 React Context API 传递 Props
你可能已经遇到过这样的情况:你拥有深度嵌套的组件,需要将 props 从上层传递到下层,而中间的一些组件只是让这些 props 传递。你可以使用 React Context API,而不必逐一修改链中的每个组件。
在此示例中,我们在一个单独的文件中创建一个新的上下文,例如:
import React from 'react'
const AuthContext = React.createContext({})
export const AuthProvider = AuthContext.Provider
export default AuthContext
然后我们需要包装父元素,因此我们希望使用我们创建的提供程序来分发道具的最高层:
import React from 'react'
import ChildComponent from './components/ChildComponent'
import { AuthProvider } from './context/AuthContext'
function ParentComponent() {
const auth = { userId: '123456', loggedIn: true }
return (
<AuthProvider value={auth}>
<ChildComponent />
</AuthProvider>
)
}
现在,ParentComponent 的所有子组件都可以使用 auth 作为 prop。是不是很酷?
接下来我们要做的就是在子组件中使用该 context。我将使用函数式组件和 useContext Hook 来实现:
import React, { useContext } from 'react'
import AuthContext from './context/AuthContext'
function ChildComponent() {
const auth = useContext(AuthContext)
console.log(auth) // { userId: '123456', loggedIn: true }
return null
}
如果嵌套了更多子组件,它们也可以访问上下文。太棒了!
样式组件
Styled-Components 实际上是 CSS-in-JS 库的一部分,它将 CSS 抽象到组件级别,仅使用 JavaScript 来描述样式。它们可以通过 ES6 模板字面量表示法使用反引号来创建,如下所示:
// install styled components with npm install styled-components
import styled from 'styled-components';
const MyButton = styled.button`
background: ${props => props.primary ? "green" : "white"};
color: ${props => props.primary ? "white" : "green"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid green;
border-radius: 3px;
`;
render(
return {
<div>
<MyButton>Normal</MyButton>
<MyButton primary>Primary</MyButton>
</div>
}
)
现在,您有了一个自定义样式的按钮组件,可以在应用程序中随处使用,取代普通的 HTML 按钮。所有样式都经过封装,不会干扰 DOM 中的其他样式。这很神奇吧?
React 片段
长期以来,你必须将所有内容都包裹在 return 语句中,放入单个 div 中,以便 React 能够将其正确渲染到 DOM 中,或者使用数组表示法。示例:
const myComponent1 = () => {
return
<div>
<Card key="1" />,
'Some Text',
<Card key="2" title="someTitle" content="Just some Content" />
</div>
}
const myComponent2 = () => {
return [
<Card key="1" />,
'Some Text',
<Card key="2" title="someTitle" content="Just some Content" />
]
}
随着 React Fragments 的引入,您不再需要使用这两种方法中的任何一种,而是可以执行以下操作:
const myComponent1 = () => {
return
<Fragment>
<Card key="1" />,
'Some Text',
<Card key="2" title="someTitle" content="Just some Content" />
</Fragment>
}
甚至从 Babel 7 开始也是如此:
const myComponent1 = () => {
return
<>
<Card key="1" />,
'Some Text',
<Card key="2" title="someTitle" content="Just some Content" />
</>
}
这很酷吧?
使用错误边界
应用程序中出现错误是一回事,但如果它们出现在视图中,至少不应该破坏整个应用程序。为此,React 中已经实现了“错误边界”。这些组件本质上是可以用来包裹其他组件的。它们会在渲染过程中以及生命周期方法中捕获错误。通过 componentDidCatch 方法(请注意,目前还没有 React Hook 来实现此功能,因此您必须使用基于类的组件),您可以对错误做出响应,并渲染回退或记录错误。以下是一个简短的示例:
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
componentDidCatch(error, info) {
// using state to initiate a fallback UI render
this.setState({ hasError: true });
// You can also log the error, for example to a service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// Rendering the actual fallback UI
return <h1>This error is unknown - too bad!.</h1>;
}
return this.props.children;
}
}
您现在可以像这样使用这个 ErrorBoundary 组件:
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
React 和 Typescript
Typescript 是一个非常热门的话题,也是开发者近期学习的首选之一。在新版本的 create-react-app (CRA) 中,它内置了对 Typescript 的支持。您只需在使用 CRA 创建新项目时添加 --typescript 标志,如下所示:
npm create-react-app my-app --typescript
在 React 中使用 Typescript 的主要好处是:
- 最新的 JavaScript 功能可用
- 复杂类型定义的接口
- VS Code 是为 TypeScript 制作的
- 可读性和验证以避免开发过程中出现错误
以下是在功能性 React 组件中使用 TypeScript 的简单示例:
import * as React from 'react';
const MyComponent: React.FunctionComponent<{
name: string
}> = (props) => {
return <h1>{props.name}</h1>
}
export default myComponent;
或者使用接口:
interface Props {
name: string
}
const MyComponent: React.FunctionComponent<Props> = (props) => {
return <h1>{props.name}</h1>
}
如果您想在 2020 年学习一些新东西,一定要尝试一下 TypeScript!
Jest + Enzyme 用于测试
测试应用程序是每个开发人员都应该做的事情,而且在许多公司中也是强制性的。使用正确的设置,测试 React 应用程序会非常酷。一种广泛使用的设置是 Jest + Enzyme。来看看吧!
Jest 默认自带 create-react-app 包,它是一个测试运行器、断言库和模拟库。它还提供快照测试,基本上就是创建组件的渲染快照,并自动与之前的快照进行比较。如果两者不匹配,测试就会失败。
这对于单元测试和集成测试来说非常实用,但对于 React 应用的真实组件来说呢?Enzyme 是一个 React 组件测试库,由 Airbnb 开发和维护,是 Jest 的理想合作伙伴。
有了这些库,我们可以进行如下简洁的测试:
it("will render correctly", () => {
const wrapper = shallow(
<MyComponent />
)
expect(wrapper).toMatchSnapshot();
})
测试某个组件的基本渲染行为。但我们还可以做更多的事情,例如测试 props:
// We need to mock zum props first
const user = {
name: 'ThePracticalDev',
email: 'TPD@dev.to',
username: 'tpd',
image: null
}
// Then the tests
describe ('<UserProfile />', () => {
it ('contains h3', () => {
const wrapper = mount(<UserProfile user={user} />)
const value = wrapper.find('h3').text()
expect(value).toEqual('ThePracticalDev')
})
it ('accepts user props', () => {
const wrapper = mount(<UserProfile user={user} />);
expect(wrapper.props().user).toEqual(user)
})
})
看起来很棒,对吧?而且,你还可以用这个设置做很多事情,比如模拟 API 调用或测试生命周期方法……
JSX 中的条件语句
编写 JSX 非常酷,也是 React 的主要功能之一。为了提升你的能力,你可以使用这个小技巧:
而不是使用
{ return loginAttempts < maxAttempts ? <MyComponent/> : null }
你可以做一个短路评估
{ return loginAttempts < maxAttempts && <MyComponent/> }
高阶组件
高阶组件 (HOC) 是 React 中一个高级概念,用于抽象共享代码,使其在需要时可访问。这个概念类似于 JavaScript 中的高阶函数,因此 HOC 本质上是接受组件并返回组件,但它们本身不是组件,而是函数。从抽象层面来看,它看起来像这样:
const MyNewComponent = (MyBaseComponent) => {
// ... copy old component, add additional data/functionality and update
return UpdatedComponent
}
Redux 的“connect”就是一个很好的例子。更实际的例子如下:
const colorizeElement = Element => props => <Element {...props} color="blue" />
首先,我们创建一个 HOC(colorizeElement),其中包含一个元素,该元素保留其所有 props,并获取一个颜色(蓝色)的新 props。我们可以使用该 HOC 创建一个蓝色的新按钮,如下所示:
const MyButton = () => {
return <button>I am a Button</button>
}
const ColoredButton = colorizeElement(MyButton)
function MyComponent() {
return (
<div className="MyComponentClass">
<h1>Hello you colored Button</h1>
<ColoredButton />
</div>
)
}
看起来很酷,对吧?
React DevTools
React DevTools 是一款非常酷的浏览器扩展程序,适用于 Chrome 和 Firefox,由 Facebook React 核心团队维护。版本 4 于 2019 年 8 月发布,对于任何 React 开发者来说,这款扩展程序都非常有用。
它与 React 和 React Native 配合良好,并真正帮助您了解 React App 内部发生的情况。
真正酷的是,你可能没有意识到这一点 - 一些大公司,如 Airbnb 和 Netflix,正在使用 React,如果你访问他们的网站,你可以在浏览器控制台中找到有关他们网站的信息(如果你安装了 React DevTools):
看到大佬们的成果总是令人欣喜。Redux DevTools 也同样如此!
奖励:React 开发人员必备的 VS Code 扩展
好了,你已经一路走到这一步了。是时候来点小奖励了。我列出了一些最适合 React 开发者的 VS Code 扩展:
ES7 React/Redux/GraphQL/React-Native 代码片段
一个非常酷的扩展,下载量接近 400 万次,为您带来大量有关 React、Redux 和 GraphQL 的代码片段。
Jest / Jest 片段
两个与 Jest 完美兼容的扩展,为您提供更好的测试代码片段
Typescript React 代码片段
如果您使用 Typescript + React,这是一个很酷的扩展,可以为您提供帮助。
虽然这些是专门针对 React 开发的扩展,但您也应该使用一些更通用的扩展。如果您已经写了一篇关于2020 年前端开发者十大最佳 VS Code 扩展的文章,请务必也查看一下!
结论
好了,一切都结束了,本文就到这里。我希望能够为您提供一些见解,帮助您成为更优秀的 React 开发者,无论您是刚刚入门还是经验丰富的开发者。如果您也像我一样热衷于 Vue 开发,那么您应该看看我的另一篇文章《10 个技巧和窍门,助您成为更优秀的 VueJS 开发者》。我很乐意听取您的意见和其他重要方面,所以请随时发表评论,并关注我,了解更多后续文章!
文章来源:https://dev.to/simonholdorf/10-tips-tricks-that-will-make-you-a-better-reactjs-dev-4fhn