返回顶部
首页 > 资讯 > 精选 >setState如何在react 中使用
  • 259
分享到

setState如何在react 中使用

2023-06-14 11:06:47 259人浏览 独家记忆
摘要

setState如何在React 中使用?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。setState是同步还是异步自定义合成事件和react钩子函数中异步更新state以

setState如何在React 中使用?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

setState是同步还是异步

自定义合成事件和react钩子函数中异步更新state

以在自定义click事件中的setState为例

import React, { Component } from 'react';class Test extends Component {  constructor(props) {    super(props);    this.state = {      count: 1    };  }  handleClick = () => {    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);  }  render() {    return (      <div style={{ width: '100px', height: '100px', backgroundColor: "yellow" }}>          {this.state.count}      </div>    )  }}export default Test;

点击一次,最终this.state.count的打印结果是1,页面展示的是2。通过现象看,三次setState只是最后一次setState生效了,前两次都setState无效果。因为假如把第一次setState改为+3,count打印结果为1,展示结果为2,没有发生变化。而且没有同步获得count的结果。

此时,我们可以调整代码,通过setState的第二个参数,来获得更新后的state:

import React, { Component } from 'react';class Test extends Component {  constructor(props) {    super(props);    this.state = {      count: 1    };  }  handleClick = () => {    this.setState({      count: this.state.count + 3    }, () => {      console.log('1', this.state.count)    });    this.setState({      count: this.state.count + 1    }, () => {      console.log('2', this.state.count);    });    this.setState({      count: this.state.count + 1    }, () => {      console.log('3', this.state.count);    });    console.log(this.state.count);  }  render() {    return (      <div style={{ width: '100px', height: '100px', backgroundColor: "yellow" }}>          {this.state.count}      </div>    )  }}export default Test;

此时,点击一次,三个setState的回调函数中,打印结果分别是。

1
1: 2
2: 2
3: 2

首先,最后一行直接打印1。然后,在setState的回调中,打印出的结果都是最新更新的2。虽然前两次setState未生效,但是它们第二个参数中还是会打印出2。

此时将setState的第一个参数换成函数,通过函数的第一个参数可以获得更新前的state。

import React, { Component } from 'react';class Test extends Component {  constructor(props) {    super(props);    this.state = {      count: 1    };  }  handleClick = () => {    this.setState((prevState, props) => {      return { count: prevState.count + 1 }    });    this.setState((prevState, props) => {      return { count: prevState.count + 1 }    });    this.setState((prevState, props) => {      return { count: prevState.count + 1 }    });    console.log(this.state.count);  }  render() {    return (      <div style={{ width: '100px', height: '100px', backgroundColor: "yellow" }}>          {this.state.count}      </div>    )  }}export default Test;

此时,打印出的结果为1,但是页面展示出来的count为4。可以发现,如果setState以传参的方式去更新state,几次setState并不会只更新最后一次,而是几次更新state都会生效。

接下来看下第二个函数中打印的count是多少:

import React, { Component } from 'react';class Test extends Component {  constructor(props) {    super(props);    this.state = {      count: 1    };  }  handleClick = () => {    this.setState((prevState, props) => {      return { count: prevState.count + 1 }    }, () => {      console.log('1', this.state.count);    });    this.setState((prevState, props) => {      return { count: prevState.count + 1 }    }, () => {      console.log('2', this.state.count);    });    this.setState((prevState, props) => {      return { count: prevState.count + 1 }    }, () => {      console.log('3', this.state.count);    });    console.log(this.state.count);  }  render() {    return (      <div style={{ width: '100px', height: '100px', backgroundColor: "yellow" }}>          {this.state.count}      </div>    )  }}export default Test;

此时,点击一次,三个setState的回调函数中,打印结果如下,可想而知,页面的展示结果也为4

1
1: 4
2: 4
3: 4

将上边代码放入如componentDidMount中,输出结果跟上边一致。

因为,可以得知,在自定义合成事件和钩子函数中,state的更新是异步的。

原生事件和setTimeout中同步更新state

以在setTimeout中setState为例

import React, { Component } from 'react';class Test extends Component {  constructor(props) {    super(props);    this.state = {      count: 1    };  }  componentDidMount() {    setTimeout(() => {      this.setState({        count: this.state.count + 1      }, () => {        console.log('1:', this.state.count);      });      this.setState({        count: this.state.count + 1      }, () => {        console.log('2:', this.state.count);      });      this.setState({        count: this.state.count + 1      }, () => {        console.log('3:', this.state.count);      });      console.log(this.state.count);    }, 0);  }  render() {    return (      <div         style={{           width: '100px',           height: '100px',           backgroundColor: "yellow"         }}>          {this.state.count}      </div>    )  }}export default Test;

此时,打印出的结果如下:

2
2: 3
3: 4
4

将setState第一个参数换为函数:

componentDidMount() {  setTimeout(() => {    this.setState((prevState, props) => {      return { count: prevState.count + 1 }    }, () => {      console.log('1', this.state.count);    });    this.setState((prevState, props) => {      return { count: prevState.count + 1 }    }, () => {      console.log('2', this.state.count);    });    this.setState((prevState, props) => {      return { count: prevState.count + 1 }    }, () => {      console.log('3', this.state.count);    });    console.log(this.state.count);  }, 0);}

打印出的结果和上边一致。

是不是有一种state完全可控的感觉,在setTimeout中,多次setState都会生效,而且在每一个setState的第二个参数中都可以得到更新后的state。

同样地,在原生事件中输出地结果和setTimeout中一致,也是同步的。

import React, { Component } from 'react';class Test extends Component {  constructor(props) {    super(props);    this.state = {      count: 1    };  }  componentDidMount() {    document.body.addEventListener('click', this.handleClick, false);  }  componentWillUnmount() {    document.body.removeEventListener('click', this.handleClick, false);  }  handleClick = () => {    this.setState((prevState, props) => {      return { count: prevState.count + 1 }    }, () => {      console.log('1', this.state.count);    });    this.setState((prevState, props) => {      return { count: prevState.count + 1 }    }, () => {      console.log('2', this.state.count);    });    this.setState((prevState, props) => {      return { count: prevState.count + 1 }    }, () => {      console.log('3', this.state.count);    });    console.log(this.state.count);  }  render() {    return (      <div        style={{           width: '100px',           height: '100px',           backgroundColor: "yellow"         }}      >        {this.state.count}      </div>    )  }}export default Test;

setState相关源码

如下代码均来自react17.0.2版本

目录 ./packages/react/src/ReactBaseClasses.js

function Component(props, context, updater) {  this.props = props;  this.context = context;  // If a component has string refs, we will assign a different object later.  this.refs = emptyObject;  // We initialize the default updater but the real one gets injected by the  // renderer.  this.updater = updater || ReactNoopUpdateQueue;}Component.prototype.isReactComponent = {};Component.prototype.setState = function(partialState, callback) {  invariant(    typeof partialState === 'object' ||      typeof partialState === 'function' ||      partialState == null,    'setState(...): takes an object of state variables to update or a ' +      'function which returns an object of state variables.',  );  this.updater.enqueueSetState(this, partialState, callback, 'setState');};

setState可以接收两个参数,第一个参数可以是object,function,和null,undefined,就不会抛出错误。执行下边的this.updater.enqueueSetState方法。全局查找enqueueSetState,找到两组目录下有这个变量。

首先是第一组目录:

目录 ./packages/react/src/ReactNoopUpdateQueue.js 第100行enqueueSetState方法,参数分别为this,初始化state,回调,和字符串setState,this是指当前React实例。

enqueueSetState: function(  publicInstance,  partialState,  callback,  callerName,) {  warnNoop(publicInstance, 'setState');}

接着看warnNoop方法:

const didWarnStateUpdateForUnmountedComponent = {};function warnNoop(publicInstance, callerName) {  if (__DEV__) {    const constructor = publicInstance.constructor;    const componentName =      (constructor && (constructor.displayName || constructor.name)) ||      'ReactClass';    const warningKey = `${componentName}.${callerName}`;    if (didWarnStateUpdateForUnmountedComponent[warningKey]) {      return;    }    console.error(      "Can't call %s on a component that is not yet mounted. " +        'This is a no-op, but it might indicate a bug in your application. ' +        'Instead, assign to `this.state` directly or define a `state = {};` ' +        'class property with the desired state in the %s component.',      callerName,      componentName,    );    didWarnStateUpdateForUnmountedComponent[warningKey] = true;  }}

这段代码相当于给didWarnStateUpdateForUnmountedComponent对象中加入属性,属性的key为React 当前要setState的组件.setState,如果当前有这个属性则返回;如果当前没这个属性或者这个属性值为false,则设置这个属性的值为true。

再去看另外一个目录:

目录 ./react-reconciler/src/ReactFiberClassComponent.new.js和ReactFiberClassComponent.old.js

const classComponentUpdater = {  enqueueSetState(inst, payload, callback) {    const fiber = getInstance(inst);    const eventTime = requestEventTime();    const lane = requestUpdateLane(fiber);    const update = createUpdate(eventTime, lane);    update.payload = payload;    if (callback !== undefined && callback !== null) {      if (__DEV__) {        warnOnInvalidCallback(callback, 'setState');      }      update.callback = callback;    }    enqueueUpdate(fiber, update, lane);    const root = scheduleUpdateOnFiber(fiber, lane, eventTime);    if (root !== null) {      entangleTransitions(root, fiber, lane);    }    if (__DEV__) {      if (enableDebugTracing) {        if (fiber.mode & DebugTracingMode) {          const name = getComponentNameFromFiber(fiber) || 'Unknown';          logStateUpdateScheduled(name, lane, payload);        }      }    }    if (enableSchedulingProfiler) {      markStateUpdateScheduled(fiber, lane);    }  }}

其中主要看 enqueueUpdate 这个函数

目录 ./react-reconciler/src/ReactUpdateQueue.new.js和ReactUpdateQueue.old.js

export function enqueueUpdate<State>(  fiber: Fiber,  update: Update<State>,  lane: Lane,) {  const updateQueue = fiber.updateQueue;  if (updateQueue === null) {    // Only occurs if the fiber has been unmounted.    return;  }  const sharedQueue: SharedQueue<State> = (updateQueue: any).shared;  if (isInterleavedUpdate(fiber, lane)) {    const interleaved = sharedQueue.interleaved;    if (interleaved === null) {      // This is the first update. Create a circular list.      update.next = update;      // At the end of the current render, this queue's interleaved updates will      // be transfered to the pending queue.      pushInterleavedQueue(sharedQueue);    } else {      update.next = interleaved.next;      interleaved.next = update;    }    sharedQueue.interleaved = update;  } else {    const pending = sharedQueue.pending;    if (pending === null) {      // This is the first update. Create a circular list.      update.next = update;    } else {      update.next = pending.next;      pending.next = update;    }    sharedQueue.pending = update;  }  if (__DEV__) {    if (      currentlyProcessingQueue === sharedQueue &&      !didWarnUpdateInsideUpdate    ) {      console.error(        'An update (setState, replaceState, or forceUpdate) was scheduled ' +          'from inside an update function. Update functions should be pure, ' +          'with zero side-effects. Consider using componentDidUpdate or a ' +          'callback.',      );      didWarnUpdateInsideUpdate = true;    }  }}

关于setState如何在react 中使用问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网精选频道了解更多相关知识。

--结束END--

本文标题: setState如何在react 中使用

本文链接: https://lsjlt.com/news/270562.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • setState如何在react 中使用
    setState如何在react 中使用?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。setState是同步还是异步自定义合成事件和react钩子函数中异步更新state以...
    99+
    2023-06-14
  • React Context与setState如何使用
    这篇文章主要介绍“React Context与setState如何使用”,在日常操作中,相信很多人在React Context与setState如何使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对...
    99+
    2023-07-04
  • React组件中的state和setState如何使用
    本篇内容主要讲解“React组件中的state和setState如何使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“React组件中的state和setState如何使用”吧!state的基本...
    99+
    2023-06-29
  • React中setState如何使用与如何同步异步
    这篇文章主要介绍“React中setState如何使用与如何同步异步”,在日常操作中,相信很多人在React中setState如何使用与如何同步异步问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”React中s...
    99+
    2023-06-14
  • React中setState使用原理解析
    目录setState使用详解使用setState的原因setState的基本用法setState的异步更新setState获取异步结果setState一定是异步setState使用详...
    99+
    2022-11-13
    React setState使用 React setState
  • React中的setState/useState怎么使用
    这篇文章主要介绍“React中的setState/useState怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“React中的setState/useState怎么使用”文章能帮助大家解决问...
    99+
    2023-07-05
  • React如何使用useEffect解决setState副作用
    本篇内容主要讲解“React如何使用useEffect解决setState副作用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“React如何使用useEffect解决setState副作用”吧!...
    99+
    2023-07-04
  • react如何在React html中使用
    本篇文章为大家展示了react如何在React html中使用,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。基本使用<!DOCTYPE html><html l...
    99+
    2023-06-14
  • React中setState的使用与同步异步的使用
    在react中,修改状态如果直接使用this.state,不会引起组件的重新渲染,需要通过 this.setState来对组件的属性进行修改。 1、this.setState的两种...
    99+
    2024-04-02
  • React中setState同步异步场景的使用
    目录setState同步异步场景描述原理保证内部数据统一启用并发更新参考setState同步异步场景 React通过this.state来访问state,通过this.setStat...
    99+
    2024-04-02
  • react中state以及setState怎么用
    这篇文章主要介绍react中state以及setState怎么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!在react中通过 state 以及 setState() 来控制组件的...
    99+
    2024-04-02
  • React中setState/useState的使用方法详细介绍
    目录一、React如何使用setState/useState的最新的值A.使用setState的最新的值B.使用useState的最新的值二、React中setState/useSt...
    99+
    2023-05-14
    React setState与useState React setState React useState
  • 在React中如何使用Vuex
    这篇文章给大家分享的是有关在React中如何使用Vuex的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。如何使用一:创建Store实例:与vuex一样,使用单一状态树(一个对象)包...
    99+
    2024-04-02
  • hook如何在react中使用
    今天就跟大家聊聊有关hook如何在react中使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1、什么是hook?react hook是react 16.8推出的方法,能够让函数式...
    99+
    2023-06-14
  • React使用useEffect解决setState副作用详解
    目录介绍一下APIfetch()方法访问APIsetState的副作用使用useEffect解决这个问题使用useEffect操控函数运行介绍一下API 本文主要内容:描述了setS...
    99+
    2022-11-13
    React useEffect解决setState React useEffect setState
  • React中多个setState会调用多少次
    这篇文章将为大家详细讲解有关React中多个setState会调用多少次,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1. 两个setState,调用几次?如下代码所示,state中有一个count。对按...
    99+
    2023-06-25
  • 使用react在修改state中的数组和对象数据的时候(setState)
    目录react修改state的数组和对象数据的时候(setState)需要注意react修改数组对象的注意事项删除数组中的指定元素合并两个对象修改多层级对象的值react修改stat...
    99+
    2024-04-02
  • 如何在React项目中使用AntDesign
    目录0.前言1.AntDesign是什么?2.AntDesign如何使用?3.如何具体使用AntDdesign的组件3-1.如何使用 antd 的Table组件3-2.如何使用 an...
    99+
    2024-04-02
  • 在react中如何使用mockjs方法
    本篇内容主要讲解“在react中如何使用mockjs方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“在react中如何使用mockjs方法”吧!介绍mock意为“模仿”或"模拟&qu...
    99+
    2023-06-29
  • 在HTML页面中如何使用React
    这篇文章主要介绍了在HTML页面中如何使用React的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇在HTML页面中如何使用React文章都会有所收获,下面我们一起来看看吧。该方案使用场景:在html页面中使用r...
    99+
    2023-06-29
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作