useState
react 是基于数据是不可变的(每次 setState 都会返回一个新数据),这也是为什么需要 setState()来更新数据而不能使用像 vue 的 this.state = newState 的形式更新数据的原因,其实你用 this.state=newState 确实可以改数据,但是 react 不知道数据变了。
setState 的写法可以分为两类
setState(updater, [callback])
第一个参数是一个 updater 函数;第二个参数是个回调函数(可选)
修改开关状态变量经常会用 updater 来改变状态,例如:
this.setState((state) => ({
isToggleOn: !state.isToggleOn,
}));
setState(stateChange, [callback])
第一个参数是一个对象;第二个参数是个回调函数(可选)
this.setState({ number: 2 });
注意: setState()不是立刻更新组件。其可能是批处理或推迟更新。这使得在调用 setState()后立刻读取 this.state 的一个潜在陷阱。
state 的赋值
通常情况下的赋值
适用的类型有:数字,字符串,布尔值,null, undefined。示例如下:
this.setState({
count: 1,
title: "React",
success: true,
});
数组类型的赋值
- 如有一个数组类型的状态 books,当向 books 中增加一本书时,使用数组的 concat 方法或 ES6 的数组扩展语法(spread syntax)
var books = this.state.books;
// 方法一:将state先赋值给另外的变量,然后使用concat创建新数组
this.setState({
books: books.concat(['三体']);
})
// 方法二:使用state、concat创建新数组
this.setState(state => ({
books: state.books.concat(['三体']);
}))
// 方法三:ES6数组扩展 spread syntax
this.setState(state => ({
books: [...state.books, '三体'];
}))
- 当从 books 中截取部分元素作为新状态时,使用数组的 slice 方法:(利用 splice 返回的数组也是同理)
var books = this.state.books;
// 方法一:将state先赋值给另外的变量,然后使用slice创建新数组
this.setState({
books: books.slice(1,3);
})
// 方法二:使用state、slice创建新数组
this.setState(state => ({
books: state.books.slice(1,3);
}))
- 当从 books 中过滤部分元素后,作为新状态时,使用数组的 filter 方法:
var books = this.state.books;
// 方法一:将state先赋值给另外的变量,然后使用filter创建新数组
this.setState({
books: books.filter(item => {
return item != '三体';
});
})
// 方法二:使用state、filter创建新数组
this.setState(state => ({
books: state.books.filter(item => {
return item != '三体';
});
}))
对象类型的赋值
- 使用 ES6 的 Object.assgin 方法
var owner = this.state.owner;
// 方法一:将state先赋值给另外的变量,然后使用Object.assign创建新对象
this.setState({
owner: Object.assign({}, owner, {name: 'Jason'});
})
// 方法二:使用state、Object.assign创建新对象
this.setState(state => ({
owner: Object.assign({}, state.owner, {name: 'Jason'});
}))
- 使用对象扩展语法(object spread properties)
var owner = this.state.owner;
// 方法一:将state先赋值给另外的变量,然后使用对象扩展语法创建新对象
this.setState({
owner: {...owner, name: 'Jason'};
})
// 方法二:使用state、对象扩展语法创建新对象
this.setState(state => ({
owner: {...state.owner, name: 'Jason'};
}))
注意
与 class 组件中的 setState 方法不同,useState 不会自动合并更新对象。你可以用函数式的 setState 结合展开运算符来达到合并更新对象的效果。
const [state, setState] = useState({});
setState((prevState) => {
// 也可以使用 Object.assign
return { ...prevState, ...updatedValues };
});
惰性初始 state
initialState 参数只会在组件的初始渲染中起作用,后续渲染时会被忽略。如果初始 state 需要通过复杂计算获得,则可以传入一个函数,在函数中计算并返回初始的 state,此函数只在初始渲染时被调用:
const [state, setState] = useState(() => {
const initialState = someExpensiveComputation(props);
return initialState;
});
链接
- 使用 State Hook
- 引用文章:https://juejin.cn/post/6844903892522631175
- React useState() 使用指南
- 4 Examples of the useState Hook