赞
踩
本文用来记录和回顾react hook 的使用,因为react的函数式组件式本身是没有状态的和其他类似于class组件的功能,所以一开始,函数组件一般只作为容器组件存在,用来展示父级组件传入的值。而16.8之后出现的 hooks(钩子),打开了函数式组件的新大门。
作用:用来记录函数式组件的状态
import React, { useState } from 'react'
const [n, setN] = React.useState(0)
- import React, { useState } from 'react‘
- import ReactDOM from 'react-dom‘
-
- const App: React.FC = (props: any) => {
- const [n, setN] = useState(0)
- const handlePlus = () => {
- setN(n+1)
- }
- const handleMinus = () => {
- setN(n-1)
- }
- return (
- <div>
- <span>{ n }</span>
- <button onClick={ handlePlus }>+1</button>
- <button onClick={ handleMinus }>-1</button>
- </div>
- )
- }
- ReactDOM.render(<App />, document.getElementById('root‘))
此时就能记录该计数器的状态了。
使用注意事项:
如果我们创建的state是一个对象,是否能只更改state中的某个属性。
- const [user, setUser] = useState({
- name: 'habitat‘,
- age: 18
- })
- // 如果我只想修改其中的name属性
- <button onClick={() => { setName('ck') }}>change name </button>
- // 预期的话 只会改变其中的name属性,并保留age属性
- // 但是实际上 user会直接变成 { name: 'ck‘ },而不保留age属性
- // 正确操作是浅拷贝原来的所有属性,然后用新的属性覆盖老的属性
- <button onClick={ () => { setName({ ...user, name: 'ck' )} }>change name </button>
2. setXX(obj)如果重新修改对象,其对象地址一定要改变,如果没有改变react就不能监听到其变化。
第一次尝试
- // 尝试改写 React.useState
-
- function myUseState(initialValue) {
- var state = initialValue
- const setState = (newState) => {
- state = newState
- // 更新页面
- render()
- }
- return [state, setState]
- }
-
- const render = () => ReactDOM.render(<App />, document.getElementById('root‘))
- const App: React.FC = (props: any) => {
- const [n, setN] = myUseState(0)
- const handlePlus = () => {
- setN(n+1)
- }
- const handleMinus = () => {
- setN(n-1)
- }
- return (
- <div>
- <span>{ n }</span>
- <button onClick={ handlePlus }>+1</button>
- <button onClick={ handleMinus }>-1</button>
- </div>
- )
- }
- ReactDOM.render(<App />, document.getElementById('root‘))
-
失败告终,因为每一次重新render的时候,会使用初始值去改变了原有的已经改变了的值,即myUseState会讲state重置。
第二次冲刺:
将state提升为全局变量
- let _state
-
- function myUseState(initialValue) {
- _state = _state === undefined ? initialValue : _state;
- const setState = (newState) => {
- _state = newState
- render()
- }
- return [_state, setState];
- }
此时利用全局变量,再一次渲染时,因为全局变量已经被修改了,所以重新渲染调用
const [n, setN] = useState(0)的时候,就不会被直接覆盖掉,所以暂时是成功。为什么说是暂时的呢,因为此时只能使用一个useState。如果使用多个useState的时候,则会导致有很多个全局变量,不好管理。
第三次尝试:
将state记录成数组,并使用index去进行创建和修改
- let _state = []
- let index = 0
-
- function myUseState(initialValue) {
- const currentIndex = index
- index += 1
- _state[currentIndex] = _state[currentIndex] || initialValue
- const setState = newState => {
- _state[currentIndex] = newState
- render
- }
- return [_state[currentIndex], setState]
- }
-
- const render = () => {
- // 将index重置为0
- index = 0
- ReactDOM.render(<App />, document.getElementById('root‘))
- }
将state记录成一个数组,当进行初始化时,每一次初始化都能记录到对应的下标,而改变时,也都能都对其对应下标进行改变。但是不能够条件性的进行初始化,这样的话会导致对应下标的数据错误。
每个函数组件都会对应一个React节点
每个节点都保存着state和index
useState会读取state[index]
index由useState的出现的顺序决定
setState会修改state,并触发更新
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。