Hooks-useState

321 阅读2分钟
/**https://zhuanlan.zhihu.com/p/92349623
 * 执行顺序解析:https://cloud.tencent.com/developer/article/1629182
 * 是useState顺序很重要:https://www.cnblogs.com/fengyuqing/p/15074207.html
 * useState
 * 1 通过多次调用useState拥有多种状态
 *   要确保对useState()的多次调用在渲染之间始终保持相同的顺序(后面会讲)。
 * 2 状态的延迟初始化
 * 每当 React 重新渲染组件时,都会执行useState(initialState)。如果初始状态是原始值(数字,布尔值等),则不会有性能问题。
    当初始状态需要昂贵的性能方面的操作时,可以通过为useState(computeInitialState)提供一个函数来使用状态的延迟初始化
 * 3 在使用useState() Hook 时,必须遵循 Hook 的规则
    仅顶层调用 Hook :不能在循环,条件,嵌套函数等中调用useState()。在多个useState()调用中,渲染之间的调用顺序必须相同。
仅从React 函数调用 Hook:必须仅在函数组件或自定义钩子内部调用useState()。
 * 4 过时状态
    当闭包捕获过时的状态变量时,就会出现过时状态的问题。可以通过使用一个回调来更新状态来解决这个问题,这个回调会根据先前的状态来计算新的状态。
    用setCount(count => count + 1)来替换etCount(count + 1)从而解决问题
 * 5 复杂状态管理
    对于复杂的状态管理,可以使用useReducer()
 * 6 状态和引用 
 * 7 严格遵守hooks规则,可安装eslint-plugin-react-hooks检查
 *   配置:package.json
  "eslintConfig":{
    "extends":"react-app",
    "plugins":[
      "react-hooks"
    ],
    "rules":{
      "react-hooks/rules-of-hooks":"error"
    }
  },
 */
import { processPluginHooks } from '@tarojs/runtime';
import React,{useState} from 'react';
let id = 0;
let firstRender = true;
export default  function App(){ let initName; 
    /**这是错误用法 */
    if(firstRender){
      [initName] = useState("Rudi");
      firstRender = false;
    }
    const [firstName, setFirstName] = useState(initName);
    const [lastName, setLastName] = useState("Yardley");
   
    return (
      <button onClick={() => setFirstName("Fred")}>Fred</button>
    );

}
function App2(){
    /**这是错误用法 */
    let name , setName;
    let count, setCount;
    id += 1;
    /*if(id & 1){
        [count,setCount] = useState(0);
        [name,setName] = useState('Mick');
    }else{
        [name,setName] = useState('Mick');
        [count,setCount] = useState(0);
    }*/
    
    [count,setCount] = useState(0);
    [name,setName] = useState('Mick');
    if(id===1){
        useState('ss')
    }

    return(
        <button onClick={()=>{setCount(count+1)}}>
            Click({count}),name({name})
        </button>
    )
}

function Bulbs(props){
    const [on,setOn] = useState(false);
    //const [count,setCount] = useState(1);
    //使用延迟初始化
    const [count,setCount] = useState(()=>{
        //此函数在渲染中只会渲染一次
        console.log('initial count');
        return props.defaultCount || 0;
    })
    const [asyCount,setAsyCount] = useState(0);

    const handleClickAsync = () =>{
        setTimeout(function delay(){
            setAsyCount(asyCount + 1);
            //正确使用:确保最新状态值作为参数提供给更新状态函数
            //setAsyCount(asyCount => asyCount+1)
        },1000)
    }

    const lightSwitch = () =>setOn(!on);
    const addBulbs = () => setCount(count => count + 1);

    return(
        <>
            <button onClick={lightSwitch}>on/off:{String(on)}</button>
            <button onClick={addBulbs}>add Bulbs:{count}</button>
            <button onClick={handleClickAsync}>asy Count:{asyCount}</button>
        </>
    )
}