主题:react函数式组件
1、state和useState
更新state会引起该组件更新,如果state绑定视图,而没有其他处理,会引起子组件更新,造成不必要的渲染
2、useMemo
使用useMemo把跟state更新不相关的返回值缓存起来
3、useRef
使用useRef可以缓存组件更新前的值
const ref = useRef(1);
<div
className={style.upload}
onClick={() => {
console.log(ref.current++);
}}
>
...
</div>
比如使用ref.current储存setTimeout、 setInterval的ID值,以后可以被clear掉。
4、useEffect和useLayoutEffect
前者是在页面渲染后执行副作用,后者实在页面渲染前执行副作用。
大多数情况下使用useEffect,也就是说在页面渲染后再执行副作用就不会造成页面卡顿。
如果需要在副作用中执行DOM操作,并且会影响DOM,则使用useLayoutEffect,就不用引起闪动。
否则在useEffect中操作DOM,页面渲染后会再次改变DOM从而引起页面闪动。
5、useCallback(fn, deps) 相当于 useMemo(() => fn, deps)
6、用useImperativeHandle、forwardRef、createRef调用组件中方法
//使用forwardRef包装子组件Title
export const Title = forwardRef((props, ref) => {
const test = () => {
console.log('test');
};
//使用useImperativeHandle对外暴露自身的test方法,可对该方法对外自定义名称如update
useImperativeHandle(
ref,
() => ({
update: () => {
test();
},
}),
[],
);
return (
<div className={style.title}>
</div>
);
});
//父组件调用
export default function HotLabel(props) {
//使用createRef获取子组件Title相关属性
let ref = createRef();
useEffect(() => {
//可以获取到子组件Title对外暴露的update方法并执行
ref.current.update();
});
return useMemo(() => {
return (
<Title label={label} ref={ref}></Title>
);
}, []);
}
相当于vue的ref获取子组件实例,react的hook更清晰,指定函数式组件内某些方法或数据可对外暴露,方便维护
7、总结
(1)函数式组件都要对影响dom渲染的变量进行useState来创建
(2)对不影响dom渲染的变量进行useRef来创建
(3)对函数进行useCallback来创建
(4)对dom进行useMemo来创建
因为这些hooks会根据deps的变化来决定hooks的变量、函数、渲染的dom等是否重新执行。