useState

235 阅读2分钟

1.useState返回的是什么

返回一个数组!!!

const [state, setState] = useState(intialValue) 数组解构形式而已

数组的第一项是:state

数组的第二项是:setState

2.状态更新变化后,react会重新渲染组件。

导致react一直在重复渲染。

场景: 计算react渲染组件的次数

  • 错误写法:

     const [state, setstate] = useState(0) 
    
     useEffect(() => {
    
       setstate(state => state + 1)
    
      })
    

state发生改变,组件重新渲染;组件渲染,state发生改变。 导致死循环

  • 正确写法 :

     使用ref来保存数据,ref保存的数据在发生变化时不会导致组件重新渲染
     const timeRef = useRef(1)
       useEffect(() => {
         timeRef.current++
       })
    

3.react每次重新渲染组件,都会执行useState

所以如果useState初始状态是原始值(数字,布尔值等),则不会有性能问题。当初始状态需要昂贵的性能方面的操作时,可以通过为useState(computeInitialState)提供一个函数来使用状态的延迟初始化。

const [state, setstate] = useState(()=>{
    //TODO: 对数据进行消耗性能的计算,比如JSON.parse
    let newValue = JSON.parse(bigData)
    return newValue
})

4.useState更新状态的方式,或者说setState()中可以传的值是什么方式

1)setState(value) : 用值来更新

(2)用回调函数来更新
    setState((state)=>{
        //TODO:对state进行操作,比如state+1
        let newState = state + 1
        return newState
    }) 
    

5.useState状态的延时更新

闭包(例如事件处理程序,回调)可能会从函数组件作用域中捕获状态变量。由于状态变量在渲染之间变化,因此闭包应捕获具有最新状态值的变量。否则,如果闭包捕获了过时的状态值,则可能会遇到过时的状态问题。

  const [state, setstate] = useState(0)
  const  handleClick = () => {
    setTimeout(() => {
      setstate(state + 1)
    }, 2000);
  }
  state是一个过时的变量 

为了解决这个问题,使用函数方法来更新count状态:

const [state, setstate] = useState(0)
  const  handleClick = () => {
    setTimeout(() => {
      setstate(state => state + 1)
    }, 2000);
  }
  

6.自己实现一个useState

let state:any ;
const useState = (initialValue:any) => {
  state = state ===undefined ? initialValue : state 
  const setstate = (newValue:any) => {
    state = newValue
    render()
  }
  return [state, setstate]
}

const render = () => {  
  ReactDOM.render(<Home />, document.getElementsById('app'));
}

一个组件中可能会有多个useState

let state: any = [];
let index = 0;
const myUseState = (initialValue: any) => {
  let renderIndex = index
  state[renderIndex] = state[renderIndex] === undefined ? initialValue : state[renderIndex]
  const setstate = (newValue: any) => {
    state[renderIndex] = newValue
    render()
  }
  index++
  return [state[renderIndex], setstate]
}

const render = () => {
  index = 0
  ReactDOM.render(<Home />, document.getElementsByClassName('lego')[0]);
}