React 开发 6 个需要注意的地方
React 作为一个流行了很久的框架,在使用方式上,仍然需要有很多注意的地方,这个视频整理了 6 个推荐的 React 代码写法,来帮助你编写效率更高,更方便复用的组件。
使用函数式组件
第一个是使用函数式组件。React 在 16.8 版本的时候发布了 Hooks,在同一时间,class 组件就不推荐使用了。因为 class 组件的代码写起来比较繁琐,例如必须使用构造函数来获取 props 和定义 state,使用 render() 方法来返回 JSX。并且 class 组件有多种生命周期,相关的代码会分散在不同的方法中,不方便统一管理:
import React, { Component } from "react";
class MyComponent extends Component {
constructor(props) {
super(props);
this.state = {
// Initial state
};
}
componentDidMount() {
// componentDidMount lifecycle method
}
componentDidUpdate(prevProps, prevState) {
// componentDidUpdate lifecycle method
}
componentWillUnmount() {
// componentWillUnmount lifecycle method
}
render() {
return <div>{/* component JSX */}</div>;
}
}
export default MyComponent;
使用函数式组件后,就和写普通 JavaScript 函数差不多,props 通过函数的参数获取,在返回语句中返回 JSX,其他的逻辑在函数体中直接编写就可以了,并且函数式组件没有生命周期,只需要使用 useEffect() hook 来控制组件的重新渲染就可以了:
import React from "react";
const MyComponent = (props) => {
// Use hooks here, if needed
useState();
useEffect();
// ...
return <div>{/* component JSX */}</div>;
};
export default MyComponent;
利用 hooks 复用逻辑
第二个是利用 hooks 复用逻辑。hooks 的出现就是为了复用组件的业务逻辑的,大体上组件函数里所有的代码都可以放到 hooks 中:
import { useState } from "react";
export const useCounter = (initialCount = 0) => {
const [count, setCount] = useState(initialCount);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
const reset = () => setCount(initialCount);
return { count, increment, decrement, reset };
};
在其他组件可以直接导入这些 hooks 并使用:
import React from "react";
import { useCounter } from "./useCounter";
const MyComponent = () => {
const { count, increment, decrement, reset } = useCounter();
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={reset}>Reset</button>
</div>
);
};
export default MyComponent;
import React from "react";
import { useCounter } from "./useCounter";
const MyOtherComponent = () => {
const { count, increment, decrement, reset } = useCounter();
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<button onClick={reset}>Reset</button>
</div>
);
};
export default MyOtherComponent;
hooks 的出现也代替了旧版本中的 higher order components 和 render props 的写法。
少使用 state
第三是尽量少使用 state:
- state 的变化会引起整个组件树的刷新,会带来一些性能上的损失,虽然 React 18 优化了 state 的批量更新,但同样有性能消耗。
- state 的变化也比较难追踪到,调试起来比较困难。
- 另外 state 会分散在不同的组件中,也不利于代码的维护
在编写组件时,只有在必须使用 state 的情况下再定义,我们可以通过 hooks 来减少状态的分散,例如使用 useReducer 结合 context 来集中管理状态,对于能经过其他状态计算而得出的数据,也不必定义为单独的状态。
定义可复用的组件
第四是定义可复用的组件来减少代码量,通过 props 来实现组件的自定义,利用 children 来方便组件之间的组合。组件里边可以根据 props 来展示不同的内容,或者处理不同的事件:
import React from "react";
const Button = ({ onClick, children }) => (
<button onClick={onClick}>{children}</button>
);
export default Button;
import React from "react";
import Button from "./Button";
const MyComponent = () => (
<div>
<Button onClick={() => alert("Button clicked!")}>Click me</Button>
</div>
);
export default MyComponent;
如果把这些都写在组件内部,那么这个组件就不能被其他组件复用,从而变成了一个只能处理一种情况的特殊组件。
import React from "react";
const Button = () => (
<button onClick={() => alert("Button clicked")}>Click me</button>
);
export default Button;
利用 children 减少嵌套
第五个是利用 children 来减少组件之间的嵌套。当组件嵌套层次过多的时候,我们需要层层传递 props 到最深处的组件,虽然可以利用全局状态管理或者是 context 来传递,但毕竟需要额外的代码和配置:
import React from "react";
const CardContent = ({ content }) => <p>{content}</p>;
const SimpleCard = ({ content }) => (
<div>
<h1>Simple Card</h1>
<CardContent content={content} />
</div>
);
const App = () => <SimpleCard content="This is a card." />;
export default App;
更简单的解决方法就是利用 children。这样我们可以直接在最上层的组件来组装它们,之后传递 props 或者是 state 等等之类的就很方便了:
import React from "react";
const CardContent = ({ content }) => <p>{content}</p>;
const SimpleCard = ({ children }) => (
<div>
<h1>Simple Card</h1>
<div>{children}</div>
</div>
);
const App = () => (
<SimpleCard>
<CardContent content="This is a card." />
</SimpleCard>
);
export default App;
避免不必要的 props
第六个是避免传递不必要的 props。尤其是当传递一个数据量比较大的 prop 的时候,它会占据很多的内存空间,并且影响性能。所以应该只传递子组件能够接收的 props:
const MyComponent = ({ prop1, prop2 }) => {
return (
<div>
{prop1}
{prop2}
</div>
);
};
const App = () => <MyComponent prop1="Hello" prop2="World" />;
// 传递不必要的大数据量:
const App = () => (
<MyComponent prop1="Hello" prop2="World" prop3={ /* large data */ } />
);
小结
这个就是在编写 react 项目时的 6 个推荐的实践。你学会了吗?如果有帮助请三连并关注,想学更多的开发知识,可以在评论区留言,感谢观看!
一系列的课程让你成为高级前端工程师。课程覆盖工作中所有常用的知识点和背后的使用逻辑,示例全部都为工作项目简化而来,学完即可直接上手开发!
即使你已经是高级前端工程师,在课程里也可能会发现新的知识点和技巧,让你的工作更加轻松!
《React 完全指南》课程,包含 React、React Router 和 Redux 详细介绍,所有示例改编自真实工作代码。点击查看详情。
《Vue 3.x 全家桶完全指南与实战》课程,包括 Vue 3.x、TypeScript、Vue Router 4.x、Vuex 4.x 所有初级到高级的语法特性详解,让你完全胜任 Vue 前端开发的工作。点击查看详情。
《React即时通信UI实战》课程,利用 Storybook、Styled-components、React-Spring 打造属于自己的组件库。
《JavaScript 基础语法详解》本人所著图书,包含 JavaScript 全面的语法知识和新特性, 可在京东、当当、淘宝等各大电商购买