useState使用和原理

Hooks 是 React 16 中的特性,解决函数组件想使用类组件的一些特性。

关于更多 Hooks 介绍,请参考 React 官网[1]

useState
之前是在类组件中使用状态通过 state 定义,大概代码是这样的。

import React from 'react';    
class Counter extends React.Component {    
  state = {    
    number: 0    
  }    
  handleClick = () => {    
    this.setState({    
      number: this.state.number + 1    
    })    
  }    
  render() {    
    return (    
      <>    
        <p>{this.state.number}</p>    
        <button    
          onClick={ this.handleClick }>    
          改数字    
        </button>    
      </>    
    );    
  }    
}    
function render() {    
  ReactDOM.render(<Counter />, document.getElementById('root'));    
}    
render()


但是函数组件没有实例,也没有状态。函数组件使用状态需要使用 useState 钩子。

关于 useState 的用法是,需要传入一个参数作为状态的初始值,当函数执行后会返回两个值,一个是当前状态的属性,一个是修改状态的方法。

我们通过一个计数器的例子,当点击按钮表示状态加1。

import React, {useState} from 'react';    
function Counter() {    
  const [    
    number,    
    setNumber    
  ] = useState(0)    
  return (    
    <>    
      <p>{number}</p>    
      <button    
        onClick={    
          () => setNumber(number + 1)    
        }    
      >    
        改数字    
      </button>    
    </>    
  )    
}    
function render() {    
  ReactDOM.render(<Counter />, document.getElementById('root'));    
}    
render()


现在我们已经掌握了它的用法,那么我们开始分析它的原理。

原理
我们需要写一个 useState 方法,会返回当前状态的属性和设置状态的方法,每当状态改变之后,方法中会调用刷新视图的 render 方法。

let memoizedState;    
function useState (initialState) {    
  memoizedState = memoizedState || initialState    
  function setState (newState) {    
    memoizedState = newState    
    render()    
  }    
  return [memoizedState, setState]    
}


再次尝试之前的代码,依然可以正常使用,但是当多个 useState 存在的时候就有问题了,只能变一个状态了。

function Counter() {    
  const [    
    number,    
    setNumber    
  ] = useState(0)    
  const [    
    title,    
    setTitle    
  ] = useState('随机标题')    
  return (    
    <>    
      <h1>{title}</h1>    
      <p>{number}</p>    
      <button    
        onClick={    
          () => setNumber(number + 1)    
        }    
      >    
        改数字    
      </button>    
      <button    
        onClick={    
          () => setTitle(`随机标题${Math.random()}`)    
        }    
      >    
        改标题    
      </button>    
    </>    
  )    
}

现在我们需要优化我们的 Hooks ,解决多个 useState 同时使用的问题,当多个状态存在的时候,我们需要使用数组保存状态。

let memoizedStates = []    
let index = 0    
function useState (initialState) {    
  memoizedStates[index] = memoizedStates[index] || initialState    
  let currentIndex = index    
  function setState (newState) {    
    memoizedStates[currentIndex] = newState    
    render()    
  }    
  return [memoizedStates[index++], setState]    
}    
    
function Counter() {    
  const [    
    number,    
    setNumber    
  ] = useState(0)    
  const [    
    title,    
    setTitle    
  ] = useState('随机标题')    
  return (    
    <>    
      <h1>{title}</h1>    
      <p>{number}</p>    
      <button    
        onClick={    
          () => setNumber(number + 1)    
        }    
      >    
        改数字    
      </button>    
      <button    
        onClick={    
          () => setTitle(`随机标题${Math.random()}`)    
        }    
      >    
        改标题    
      </button>    
    </>    
  )    
}    
    
function render() {    
  index = 0    
  ReactDOM.render(<Counter />, document.getElementById('root'));    
}    
render()


现在已经完成了 useState 的基本原理,当你了解原理之后,使用 Hooks 就变得更加容易了。

猜你喜欢

转载自www.cnblogs.com/chenzxl/p/11827931.html