zoukankan      html  css  js  c++  java
  • 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 就变得更加容易了。

  • 相关阅读:
    设计模式
    包装类
    php 闭包的理解
    is_null empty isset等的判定
    PHP基础一 $this ,static 和 self的区别
    lumen安装踩过得坑
    composer的使用和安装
    使用submine来写c++
    php 和 thinkphp中的常量一览
    路径问题 ./ / ../ 空 的区别
  • 原文地址:https://www.cnblogs.com/chenzxl/p/11827931.html
Copyright © 2011-2022 走看看