类组件
- React. PureComponent
// class Hello extends React.Component { // 普通组件
class Hello extends React.PureComponent { // 纯组件
render() {
return (
<div>纯组件</div>
)
}
}
- shouldComponentUpdate
class Hello extends Component {
shouldComponentUpdate(props,state) {
// 根据条件,决定是否重新渲染组件
return false
}
render() {…}
}
hooks组件
-
useCallback/useMemo和memo组合,防止父组件re-render后,导致自己的函数或者值
首先,假如我们不使用useCallback,在父组件中创建了一个名为handleClick的事件处理函数,根据需求我们需要把这个handleClick传给子组件,当父组件中的一些state变化后(这些state跟子组件没有关系),父组件会reRender,然后会重新创建名为handleClick函数实例,并传给子组件,这时即使用React.memo把子组件包裹起来,子组件也会重新渲染,因为props已经变化了,但这个渲染是无意义的如何优化呢?这时候就可以用useCallback了,我们用useCallback把函数包起来之后,在父组件中只有当deps变化的时候,才会创建新的handleClick实例,子组件才会跟着reRender
(注意,必须要用React.memo把子组件包起来才有用,否则子组件还是会reRender。React.memo是类似于class组件中的Pure.Component的作用)
这个的具体使用方式可以看我其他关于其三个专门文章
- useRef解决方案
- useRef在每次reRender时不会改变,保证了父组件不会重新创建handleClick函数实例,handleClick函数能拿到最新的state
const [text, setText] = useState('Initial value');
const textRef = useRef(text);
const handleClick= useCallback(() => {
console.log(textRef.current);
}, []);
useEffect(() => {
console.log('update text')
textRef.current = text;
}, [text])
3.useReducer解决方案
- dispatch自带memoize,所以子组件不会进行 re-render
function reducer(state, action) {
switch(action.type) {
case 'update':
return action.preload;
case 'childComponent':
// 要执行的函数
return state;
}
}
export default function Index() { // 父组件
const [state, dispatch] = useReducer(reducer, 'Initial value');
return (
<>
<input value={state} onChange={(e) => dispatch({
type: 'update',
preload: e.target.value
})} />
<ChildComponent dispatch={dispatch} />
</>
)
}
//在 ChildComponent中,拿到dispatch,通过dispatch({type: 'childComponent' })的方式调用