usestate 数组增加_React Hook -- useState
本文用来记录和回顾react hook 的使用,因为react的函数式组件式本身是没有状态的和其他类似于class组件的功能,所以一开始,函数组件一般只作为容器组件存在,用来展示父级组件传入的值。而16.8之后出现的 hooks(钩子),打开了函数式组件的新大门。useState作用:用来记录函数式组件的状态使用方式import React, { useState } from 'react'co
本文用来记录和回顾react hook 的使用,因为react的函数式组件式本身是没有状态的和其他类似于class组件的功能,所以一开始,函数组件一般只作为容器组件存在,用来展示父级组件传入的值。而16.8之后出现的 hooks(钩子),打开了函数式组件的新大门。
useState
作用:用来记录函数式组件的状态
使用方式
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就不能监听到其变化。
探究useState如何实现
第一次尝试
// 尝试改写 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,并触发更新
更多推荐
所有评论(0)