useState 使用和原理

发布于 2022-09-19 21:22:08 字数 3577 浏览 123 评论 0

Hooks 是 React 16 中的特性,解决函数组件想使用类组件的一些特性,关于更多 Hooks 介绍,请参考 React 官网

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()

注意上面的代码,有个 index=0 的操作,因为添加的时候按照顺序添加的,渲染的时候也要按照顺序渲染的,现在已经完成了 useState 的基本原理,当你了解原理之后,使用 Hooks 就变得更加容易了。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

生寂

暂无简介

文章
评论
26 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文