9

Recently, the project used umi3+react17+antd pro5

UseState pits encountered in the project

1.useState is not suitable for the change of complex objects

Because useState cannot be merged and updated like setState, when using the second parameter of useState to update data, a complete structure must be passed in, not just the changed part.

2. The problem of useState asynchronous callback

When using usestate to update data, the latest data cannot be obtained immediately.

const [name, setName] = useState('dx');
const handleTest = () => {
  console.log(name) // dx
  setName('dx1')
  console.log(name) // dx
}

solution

1. Use with useEffect

const [name, setName] = useState('dx');
const handleTest = () => {
  console.log(name) //dx
  setName('dx1')
  console.log(name)//dx
}
  
useEffect(() => {
  console.log(name) //dx1
},[name])

2. Create a new variable to save the latest data

const [name, setName] = useState('dx');
const handleTest = () => {
  console.log(name) //dx
  const newName = "dx1"
  setName(newName)
  console.log(newName) //dx1
}

3. According to the rules of hook, there are restrictions on where to use useState

  • Only call Hook at the top level: useState() cannot be called in loops, conditions, nested functions, etc.
  • In multiple useState() calls, the call sequence between renderings must be the same.
  • Hook is only called from React functions: useState() must be called only inside function components or custom hooks.

4. Use useState to change the data in the form of a callback function

const [a, setA] = useState({c:1})
/** oldA为之前的a,return为设置的新值 */
setA((oldA) => {
  return {c: oldA.c + 1}
})

5. The value stored in useState is only a reference to the value (reference type)

const textObj = {name:'dx'}
const [useState1, setUseState1] = useState(textObj )
const [useState2, setUseState2] = useState(textObj )
/** usestate的操作不要放在函数的最外层,这里只是简单的代码展示,你可以将set操作放在某个函数里面 */
setUseState1((oldUseState1) => {
  oldUseState1.age = 18
  return {...oldUseState1}
})
useEffect(() => {
  /** 改变一个会导致两个都改变,深浅拷贝的问题 */
  console.log(useState1)  // {name: "dx", age: 18}
  console.log(useState2)  // {name: "dx", age: 18}
},[useState1])

Solution

const textObj = {name:'dx'}
const [useState1, setUseState1] = useState(textObj )
const [useState2, setUseState2] = useState(JSON.parse(JSON.stringify(textObj)))
/** usestate的操作不要放在函数的最外层,这里只是简单的代码展示,你可以将set操作放在某个函数里面 */
setUseState1((oldUseState1) => {
  oldUseState1.age = 18
  return {...oldUseState1}
})

useEffect(() => {
  /** 改变一个会导致两个都改变,深浅拷贝的问题 */
  console.log(useState1)  // {name: "dx", age: 18}
  console.log(useState2)  // {name: "dx"}
},[useState1])

6. useState, if you save the reference data, useEffect can't detect the change?

const textObj = {name:'dx'}
const [useState1, setUseState1] = useState(textObj)
/** usestate的操作不要放在函数的最外层,这里只是简单的代码展示,你可以将set操作放在某个函数里面 */
setUseState1((oldUseState1) => {
  oldUseState1.age = 18
  return oldUseState1
}
useEffect(() => {
  console.log(useState1)  
},[useState1])
//结果是没有任何反应

Solution

const textObj = {name:'dx'}
const [useState1, setUseState1] = useState(textObj)
/** usestate的操作不要放在函数的最外层,这里只是简单的代码展示,你可以将set操作放在某个函数里面 */
setUseState1((oldUseState1) => {
  oldUseState1.age = 18
  /** 返回一个新的对象,useEffectc才能检测得到 */
  return {...oldUseState1}
}
useEffect(() => {
  console.log(useState1)  // {name: "dx", age: 18}
},[useState1])

7. useState cannot save a function

Are you trying to save the function reference as a variable in useState?
such as:

const testFunciton1 = () => {
  console.log({name: 'dx',age: '18'})
}
/** usestate保存函数测试 */
const [stateFunction, setstateFunction] = useState<() => void>(testFunciton1);
useEffect(() => {
 console.log(stateFunction)// {name: 'dx', age: 18}
}, [stateFunction])

TestFunciton1 has never been called in the code, but testFunciton1 was executed as a result
What useEffect prints out is an undefined.

Change the code a bit, and then test

const testFunciton1 = () => {
  console.log({name: 'dx',age: '18'})
  return {
    name: 'yx',
    age: '17'
  }
}
/** usestate保存函数测试 */
const [stateFunction, setstateFunction] = useState<() => void>(testFunciton1);
useEffect(() => {
 console.log(stateFunction)// {name: 'dx', age: 18} // {name: 'yx', age: 17}
}, [stateFunction])

Obviously, in useState, the function is automatically called and the value returned by the function is saved, but the function itself cannot be saved.

Solution
If you can't save the function using useState, you can use the hook of useCallback.

/** useCallback,使用参数与useEffect一致 */
const testFunction = useCallback(() => {
  // useCallback返回的函数在useCallbak中构建
  const testFunciton1 = () => {
    console.log({ name: 'dx', age: '18' });
    return {
      name: 'yx',
      age: '17',
    };
  };
  return testFunciton1;
}, []);
useEffect(() => {
  console.log(testFunction());// 打印的是函数
}, [testFunction]);

万年打野易大师
1.5k 声望1.1k 粉丝