当前位置: 代码迷 >> 综合 >> 【React】setState
  详细解决方案

【React】setState

热度:94   发布时间:2023-12-16 18:54:39.0
//index.js
import React from "react";
import ReactDOM from "react-dom";import Counter from "./counter.js";ReactDOM.render(<Counter caption="计数器"/>,document.querySelector('#root')
)
//counter.js
import React from "react";const style = {
    marginRight:"5px"
}
class Counter extends React.Component{
    constructor(props){
    super(props);this.state = {
    count:0}this.handleIncrement = () => {
    this.setState((state,props) => {
    console.log(props);return {
    count:state.count+1}},()=>{
    console.log("当前计数:",this.state.count);})}this.handleDecrement = () => {
    this.setState({
    count:this.state.count-1}, () => {
    console.log("当前计数:",this.state.count)})}}render(){
    return (<><h3>{
    this.props.caption}</h3><button style={
    style} onClick={
    this.handleIncrement}>+</button><button style={
    style} onClick={
    this.handleDecrement}>-</button><span>{
    this.state.count}</span></>);}
}export default Counter;

在这里插入图片描述

setState 完成了两项工作:

  1. 更新state对象
  2. 驱动组件渲染,引发componentDidUpdate、render等函数调用

setState有两种使用方式:

  1. setState(updater,callback)
    第一个参数,updater,是函数,用来返回新的state对象;
    第二个参数,callback,是回调函数,state改变且渲染完成后callback会被调用。
    updater有两个参数:state和props。
    state 是 最新state(可能不太准确); props 是 从父组件传递过来的props。
  2. setState(stateChange,callback)
    第一个参数,stateChange,是一个新的state对象;
    第二个参数,callback,是回调函数,state改变且渲染完成后callback会被调用。

在这里插入图片描述
setState并不总会立即更新this.state,可能同步,也可能异步。

import React from "react";const style = {
    marginRight:"5px"
}
class Counter extends React.Component{
    constructor(props){
    super(props);this.state = {
    count:0}this.handleIncrement = () => {
    this.setState((state,props) => ({
    count:state.count+1}));this.setState((state,props) => ({
    count:state.count+1}));this.setState((state,props) => ({
    count:state.count+1}));// this.setState((state,props) => {
    // console.log("this.state.count:",this.state.count," ","state.count:",state.count);// return { count:state.count+1 }// })// this.setState((state,props) => {
    // console.log("this.state.count:",this.state.count," ","state.count:",state.count);// return { count:state.count+1 }// })// this.setState((state,props) => {
    // console.log("this.state.count:",this.state.count," ","state.count:",state.count);// return { count:state.count+1 }// })}this.handleDecrement = () => {
    this.setState({
    count:this.state.count-1});this.setState({
    count:this.state.count-1});this.setState({
    count:this.state.count-1});// this.setState({count:this.state.count-1}); console.log("this.state.count:",this.state.count);// this.setState({count:this.state.count-1}); console.log("this.state.countt:",this.state.count);// this.setState({count:this.state.count-1}); console.log("this.state.count:",this.state.count);}}static getDerivedStateFromProps(nextProps,nextState){
    console.log("enter getDerivedStateFromProps","nextState:",nextState);return null;}shouldComponentUpdate(nextProps,nextState){
    console.log("enter shouldComponentUpdate");return true;}render(){
    console.log("enter render");return (<><h3>{
    this.props.caption}</h3><button style={
    style} onClick={
    this.handleIncrement}>+</button><button style={
    style} onClick={
    this.handleDecrement}>-</button><span>{
    this.state.count}</span></>);}
}export default Counter;

在这里插入图片描述
在这里插入图片描述

本例,调用setState时,this.state 没有立即更新,到了 调用render时 才会更新,属异步更新。
多次调用setStatesetState(updater,callback)setState(stateChange,callback)都会有个合并的过程,但合并方式不同,因而最终的this.state.count不一样。不过,不论以何种方式 setState,组件都只会渲染一次。

import React from "react";const style = {
    marginRight:"5px"
}
class Counter extends React.Component{
    constructor(props){
    super(props);this.state = {
    count:0}this.handleIncrement = () => {
    this.setState(state => ({
    count:state.count+1}));console.log("setState in onClick","this.state.count:",this.state.count);}this.handleDecrement = () => {
    setTimeout(() => {
    this.setState(state => ({
    count:state.count-1}));console.log("setState in setTimeout","this.state.count:",this.state.count);})}this.handleClickA = () => {
    this.setState(state => ({
    count:state.count+1}));console.log("setState in EventListener","this.state.count:",this.state.count);}this.handleClickB = () => {
    new Promise(resolve => {
    this.setState(state => ({
    count:state.count-1}));resolve(this.state.count);}).then(count => {
    console.log("setState in Promise","this.state.count",count);})}}componentDidMount(){
    document.querySelector('#testA').addEventListener("click",this.handleClickA);document.querySelector('#testB').addEventListener("click",this.handleClickB);}componentWillUnmount(){
    document.querySelector('#testA').removeEventListener("click",this.handleClickA);   document.querySelector('#testB').removeEventListener("click",this.handleClickB);     }render(){
    console.log("enter render","this.state.count:",this.state.count);return (<><h3>{
    this.props.caption}</h3><button style={
    style} onClick={
    this.handleIncrement}>+</button><button style={
    style} onClick={
    this.handleDecrement}>-</button><button style={
    style} id='testA'>+(test)</button><button style={
    style} id='testB'>-(test)</button><span>{
    this.state.count}</span></>);}
}export default Counter;

在这里插入图片描述

addEventListener里调用setState,同步更新了this.state
setTimeout里调用setState,同步更新了this.state
Promise里调用setState,同步更新了this.state
React事件处理程序的setState,异步更新了this.state,这是因为React事件处理程序中的更新 默认会被批量处理。

参考文章
setState:这个API设计到底怎么样
何时以及为什么 setState() 会批量执行?
React 是否保持 state 更新的顺序?

  相关解决方案