ReactJS 中的 this.state 和 this.setstate 有啥区别?
Posted
技术标签:
【中文标题】ReactJS 中的 this.state 和 this.setstate 有啥区别?【英文标题】:What the difference of this.state and this.setstate in ReactJS?ReactJS 中的 this.state 和 this.setstate 有什么区别? 【发布时间】:2016-06-22 09:05:02 【问题描述】:我想更改hasSubmit
键的值,就像在第一个代码部分中一样。我知道这是不推荐的。但是第二段代码是异步的,我不想用setState
的回调函数。
this.state
和setState
有什么区别?
有什么方法可以立即改变状态值hasSubmit
?
第一个代码:
this.state.hasSubmit = false
this.setState()
//Code that will use `hasSubmit`.
第二个代码:
this.setState(
hasSubmit: false,
);
//Code that will use `hasSubmit`.
添加:
场景是这样的:
hasSubmit
在getInitialState()
中设置false
。 当我点击submit
按钮时,hasSubmit
将变为false
。 提交时hasSubmit
将更改为true
。
第一次点击submit
没问题,hasSubmit
会设置成true
。
但是第二次点击submit
使用Second asynchronous code
会出错,因为hasSubmit
还是true
,而First Code
可以解决问题。
【问题讨论】:
你想要这个的最终目标是什么?你能详细说明一下吗?我可以将您推荐给文档,但我假设您已经这样做了,所以我想知道您想要实现的目标。 【参考方案1】:React docs 是这样说的:
永远不要直接改变
this.state
,因为之后调用 setState() 可能会替换你所做的改变。将 this.state 视为不可变的。
setState()
不会立即改变 this.state 而是创建一个挂起的状态转换。调用此方法后访问this.state
可能会返回现有值。不保证 setState 调用的同步操作,并且调用可能会被批处理以提高性能。
setState()
将始终触发重新渲染,除非在shouldComponentUpdate()
中实现了条件渲染逻辑。如果正在使用可变对象并且无法在
shouldComponentUpdate()
中实现逻辑,则仅在新状态与先前状态不同时调用setState()
将避免不必要的重新渲染。
按照设计的方式使用 API 总是明智的。如果文档说不要改变你的状态,那么你最好不要改变你的状态。
虽然setState()
在技术上可能是异步的,但它肯定不会以任何明显的方式变慢。组件的render()
函数将在很短的时间内被调用。
直接设置状态的一个缺点是 React 的生命周期方法 - shouldComponentUpdate()
、componentWillUpdate()
、componentDidUpdate()
- 依赖于使用 setState()
调用的状态转换。如果直接更改状态并使用空对象调用setState()
,则无法再实现这些方法。
另一个是它只是糟糕的编程风格。你在两个语句中做你可以在一个语句中做的事情。
此外,这里没有实际的好处。在这两种情况下,render()
在调用setState()
(或forceUpdate()
)之前都不会被触发。
您声称需要这样做,但没有实际解释该需要是什么。也许您想更详细地说明您的问题。可能有更好的解决方案。
最好使用框架而不是反对它。
更新
来自下面的cmets:
需要的是我想在下面使用更改后的hasSubmit。
好的,我现在明白了。如果您需要立即使用未来状态属性,最好的办法就是将其存储在局部变量中。
const hasSubmit = false;
this.setState(
hasSubmit: hasSubmit
);
if (hasSubmit)
// Code that will use `hasSubmit` ...
【讨论】:
需要的是我想使用下面更改的hasSubmit
。
我尝试了第一个代码。方法componentWillUpdate()
、componentDidUpdate()
、render()
也将被调用,hasSubmit
的值更改为true
。
1) 我明白了。我已经更新了我的答案来解决这个问题。 2) 那些生命周期方法不能再有意义地将this.state
与nextState
或prevState
进行比较。
您说维护局部变量的事实并不好 imo。这可以通过 setstate 方法的回调作为文档来实现。
添加一个异步回调函数远比一个简单的局部变量笨重得多。它也没有抓住重点。查询状态是不必要的。你不需要get你刚刚set!【参考方案2】:
如果你想改变状态并通过react触发重新渲染: 使用第二个代码。
this.setState(
hasSubmit: false,
);
第一个代码的问题/错误:
this.state.hasSubmit = false // Updates state directly:
// You are not supposed to do this
// except in ES6 constructors
this.setState() // passes an empty state to react.
// Triggers re-render without mutating state
【讨论】:
答案清晰易懂 你说的是this code does not use setState callback:
,但在这两个例子中你都使用了setState
——这是一个错字吗?
setState
可以采用可选的回调参数。在状态更新后可以使用它来做一些事情。这并不是一个错字:我使用了setState
,但没有传递任何回调参数。这确实令人困惑,所以我删除了参考;)【参考方案3】:
this.setState
维护了 react 组件的生命周期,并且看起来不像变异变量(即使在内部它确实会改变状态)。因此,反应循环中的单向流程保持不变,没有任何副作用。
需要注意的是,使用 this.setState
不适用于 ES6 类中的构造函数。我们需要在 ES6 构造函数中使用this.state =
模式而不是this.setState
【讨论】:
是的。很好地观察到this.setState
语法在 ES6 类构造函数中是不允许的。可能是因为在构造函数中您没有修改状态,而是第一次对其进行初始化。
this.setState 不允许在构造函数中使用,因为 setState 可以批处理并且是异步的,因此这可能意味着组件最终可能具有与预期或初始化时不同的状态.出于同样的原因,也不鼓励 AJAX 调用。【参考方案4】:
您永远不应忽视文档建议。在撰写本文时,setState 允许第二个参数是 setState 和重新渲染完成时的回调函数。由于您从未向我们提供您的代码将如何使用 hasSubmit 值,我相信其他一些人可能会在他们想要确保 hasSubmit 已更改时发现这很有用。
【讨论】:
我相信这应该是答案。正如最佳答案所暗示的那样,无需维护另一个局部变量来保存该值。【参考方案5】:您应该在第一个示例中使用this.forceUpdate()
来强制更新状态。例如:
this.state.hasSubmit = false;
this.forceUpdate();
但最好使用this.setState
,因为它是 React 引擎的 init native check-state mecanizm,比强制更新更好。
如果你只是直接更新this.state
的任何参数而没有setState
,react render mecanizm 将不会知道状态的某些参数已更新。
【讨论】:
在官方文档here 中:“通常你应该尽量避免使用 forceUpdate() 并且只在 render() 中读取 this.props 和 this.state。”在这种特殊情况下, forceUpdate() 不是一个好的解决方案。 对于真正深度嵌套的状态 JSON 对象,例如深度嵌套的数组,用setState
更新状态是一件很痛苦的事情以上是关于ReactJS 中的 this.state 和 this.setstate 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我们需要在 ReactJS 中使用 bind() 来访问 this.props 或 this.state? [复制]