1、react filber
2、useMemo、useCallback、memo
先看memo
定义两个组件,一个父组件一个子组件
// 父组件
...
const Father = () => {
const [count, setCount] = useState(0);
return (
<div>
<div>count:{count}</div>
<button onClick={addCount}>增加count</button>
<Child />
</div>
);
};
export default Father;
// 子组件
const Child = () => {
console.log("子元素更新了");
return (
<div>
我是子元素
</div>
);
};
export default Child;
// export default React.memo(Child);
如果子组件没有用memo包裹,存在的问题就是每次在父组件中点击增加count,子组件没有用到额外的props也会发生render,造成不必要的资源浪费;与Class Component中的PureComponent类似,在React Hooks中,memo会对传入props进行浅比较,如果是相同的props则不会发生渲染。
注意:如果传入的对象,子元素还是会渲染,memo只能进行浅比较
再来看useCallback
const Father = () => {
const [count, setCount] = useState(0);
const onhandleUpdate = (data: number) => {
console.log("子组件触发", data);
};
return (
<div>
<div>count:{count}</div>
<button onClick={addCount}>增加count</button>
<Child onhandleUpdate={onhandleUpdate} />
</div>
);
};
export default Father;
interface IChildProps {
onhandleUpdate: (n: number) => void;
}
const Child: FC<IChildProps> = ({ onhandleUpdate }) => {
console.log("子元素更新了");
return (
<div>
我是子元素<button onClick={() => onhandleUpdate(222)}>点击子组件</button>
</div>
);
};
export default React.memo(Child);
如果子组件用到了父组件中定义的方法,即使子组件包裹了memo还是会发生渲染,因为在每次点击按钮触发更新后,onhandleUpdate函数都会被重新定义一遍,并作为一个新的变量传递给B组件。这时memo内部认为props发生了变化。此时就可以用useCallback将onhandleUpdate缓存起来,只有当依赖项发生变化时才会重新传入
const onhandleUpdate = useCallback((data: number) => {
console.log("子组件触发", data);
}, []);
再看useMemo
useCallBack和useMemo唯一的区别是:useMemo返回的是传入的回调函数的执行结果,useCallBack返回的是传入的回调函数。本质上useCallBack就是useMemo的语法糖。
const Father = () => {
const [count, setCount] = useState(0);
const getOthers = useMemo(() => {
console.log("others更新了");
return new Array(10).fill(0);
}, []);
const onhandleUpdate = useCallback((data: number) => {
console.log("子组件触发", data);
}, []);
return (
<div>
<div>count:{count}</div>
<div>其他数据:{getOthers}</div>
<button onClick={addCount}>增加count</button>
<Child onhandleUpdate={onhandleUpdate} />
</div>
);
};
export default Father;
注意:useMemo、useCallBack不要滥用,需要结合具体场景
3、useEffect、useLayoutEffect
- useEffect 是异步非阻塞调用
- useLayoutEffect 是同步阻塞调用
- useEffect 浏览器绘制后
- useLayoutEffect 在 DOM 变更(React 的更新)后,浏览器绘制前完成所有操作
绝大部分场景中都是使用useEffect。因为useLayoutEffect是同步执行的,因此会发生阻塞,直到effect执行完成才会进行页面重绘,如果你的effect内部有执行很慢的代码,可能会引起性能问题。当操作DOM时发生闪烁的问题可以尝试使用useLayoutEffect
4、react diff算法?和vue有什么区别?key的作用
聊一聊Diff算法(React、Vue2.x、Vue3.x)
5、useState是同步还是异步
React useState和setState到底是同步还是异步呢?