react知识汇总篇

134 阅读2分钟

1、react filber

React Fiber 详细解析

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

使用useEffect发生闪烁的情况

4、react diff算法?和vue有什么区别?key的作用

聊一聊Diff算法(React、Vue2.x、Vue3.x)

5、useState是同步还是异步

React useState和setState到底是同步还是异步呢?

6、为什么hooks不能放在if条件判断语句中

为什么 hooks 不能写在循环或者条件判断语句里?