laclys / Front-End_practice

Daily practice
5 stars 0 forks source link

React.StrictMode #146

Open laclys opened 3 years ago

laclys commented 3 years ago

当我们使用CRA创建React App。挂在的APP节点默认被React.StrictMode严格模式包裹了(react16.3加上的)

React.StrictMode: 是一个用来突出显示应用程序中潜在问题的工具。与 Fragment 一样,StrictMode 不会渲染任何可见的 UI。它为其后代元素触发额外的检查和警告

简单说就是会检测意外的副作用。 例如 170b9f2f75a2c7d5

state.id值为多少?

大部分人都会说1。当然生产环境确实如此。但包裹React.StrictMode下,开发环境答案是2

React.StrictMode,它在开发环境中将 constructor 函数调用了两次。

为了检测意外的副作用,通过调用两次的方式将一些隐藏地比较深的副作用放大 再比如如下例子


let cache

export default () => {
  const [name, setname] = useState('')
  const [age, setAge] = useState(18)

  // dept name变化,userInfo值变化.
  const userInfo = useMemo(() => {
    return {
      fullname: `my name is ${name}`,
    }
  }, name)

  if (!cache) {
    cache = userInfo
  }

  console.log('!!!', {
    cache,
    userInfo,
    equal: cache === userInfo,
  })

  return (
    <div>
      <input type="text" value={age} onChange={e => setAge(e.target.value)} placeholder='age'/>
      {JSON.stringify({
        name,
        age,
        userInfo,
      })}
    </div>
  )
}

name没有变化userInfo不需要重新计算, 重新渲染。但开启StrictMode之后userInfo每次返回的都是全新的对象。不受dept影响

运行代码:这里第一次打印 equal: true,没问题。这里修改input输入框age的值。按道理useMemo的dept只依赖name。但是我们每次修改age,打印出来的都是equal:false,证明userinfo还是render了,渲染出来了新对象

去掉严格模式就正常


使用严格模式开发 要慎重。不光是useMemo、useState、useCallback都不是返回同一个对象

官方说法是:通过在开发环境下故意重复调用,帮助你发现它们,使它们更具确定性。我是觉得挺坑的。

laclys commented 3 years ago

其他作用: