React Hooks初步踩坑坑

时间:2021-1-8 作者:admin

大家好,我是踩坑小星球。作为一个 Component 拥护者,迈出一小步踩下 Hook ,看看它到底是个啥玩意儿。
基础语法之类的就不说了,文章多的是,这个只是我自己在开发的时候,需要注意的点~
[TOC]

关于状态

  1. useState管理状态,这里有一点需要注意,当你使用 useState 的 set方法的时候,旧状态不会自动 merge到新状态中去,也就是 set 所改变的是全量数据。
    这句话的意思就是,如果你的 state 是一个对象,你需要手动的构成一个完整的新数据
  // 定义
  const [obj,setObj] = useState({name: "小蘑菇",age: 0 });

  // 更新
  setObj({
    ...obj,
    name: "大蘑菇"
  });

  // 结果
  // {name: "大蘑菇",age: 0 }
  1. useState产生的 state 作为函数中的一个常量,就是普通的数据,并不存在诸如数据绑定这样的操作来驱使 DOM 发生更新。在调用 setState 后,React 将重新执行 render 函数,仅此而已。因此,状态也是函数作用域下的普通变量。
    我们可以说每次函数执行拥有独立的状态,具有 Capture Value 的特性,简单来说,就是它不能实时。

  2. 利用useRef就可以绕过 Capture Value 的特性。可以认为 ref 在所有 Render 过程中保持着唯一引用,因此所有对 ref 的赋值或取值,拿到的都只有一个最终状态,而不会在每个 Render 间存在隔离。
    原因是因为,ref.current 将被赋予初始值 initialValue,之后便不再发生变化。但你可以自己去设置它的值。设置它的值不会重新触发 render 函数。

function Example() {
  const [count, setCount] = useState(0);
  // Initial ref
  const latestCount = useRef(count);

  useEffect(() => {
    // Set the mutable latest value
    latestCount.current = count;
    setTimeout(() => {
      // Read the mutable latest value
      console.log(`You clicked ${latestCount.current} times`);
    }, 3000);
  });
  // ...
}

生命周期

Component 最大的好处是有生命周期可以处理各种数据,在 Hook 也可以利用Effect钩子模拟这种生命周期

  1. 通常我们会利用组件的生命周期函数去执行一些副作用,但通常副作用逻辑复杂,可能会有 Bug,所以在 Hook 里,建议针对每一段逻辑单独使用一个Effect钩子
  useEffect(() => {
      console.log('模拟componentDidMount');
      return () => {
          console.log('模拟componentWillUnmount')
      }
  }, []);

  useEffect(() => {
      console.log('模拟componentDidMount以及name改变时,模拟componentDidUpdate');
      return () => {
          console.log('name改变时,都会先触发这里,再触发上面的effect')
      }
  }, [name]);

  1. 对于 useEffect 来说,执行的时机是完成所有的 DOM 变更并让浏览器渲染页面后,而 useLayoutEffect 和 class 组件中 componentDidMount, componentDidUpdate一致——在 React 完成 DOM 更新后马上同步调用,会阻塞页面渲染.

  2. 利用useMemo减少不必要的渲染

function Parent({ a, b }) {
  // Only re-rendered if `a` changes:
  const child1 = useMemo(() => <Child1 a={a} />, [a]);
  // Only re-rendered if `b` changes:
  const child2 = useMemo(() => <Child2 b={b} />, [b]);
  return (
    <>
      {child1}
      {child2}
    </>
  )
}

注意事项

  • 不要在循环,条件或嵌套函数中调用 Hook ,必须始终在 React 函数的顶层使用 Hook 。这是因为React需要利用调用顺序来正确更新相应的状态,以及调用相应的钩子函数。一旦在循环或条件分支语句中调用Hook,就容易导致调用顺序的不一致性,从而产生难以预料到的后果。
  • 只能在 React 函数式组件或自定义 Hook 中使用 Hook
  • 可以安装 eslint 插件eslint-plugin-react-hooks,在.eslintrc.js中加入配置
{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error"
  }
}
  • 谨慎将处于同个 useEffect dependences 之中且有逻辑关联的 state 放在多个 useEffect中
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。