Javascript 为什么可以';直接修改组件';真的吗?
我理解React教程和文档警告在该状态下不应直接变异,所有内容都应通过Javascript 为什么可以';直接修改组件';真的吗?,javascript,reactjs,Javascript,Reactjs,我理解React教程和文档警告在该状态下不应直接变异,所有内容都应通过setState currentStateCopy.push(6) this.setState({ a: currentStateCopy }) 我想知道为什么我不能直接改变状态,然后(在同一个函数中)调用this.setState({})来触发渲染 例如:下面的代码似乎工作得很好: const React = require('react'); const App = React.createClass({
setState
currentStateCopy.push(6)
this.setState({
a: currentStateCopy
})
我想知道为什么我不能直接改变状态,然后(在同一个函数中)调用this.setState({})
来触发渲染
例如:下面的代码似乎工作得很好:
const React = require('react');
const App = React.createClass({
getInitialState: function() {
return {
some: {
rather: {
deeply: {
embedded: {
stuff: 1
}}}}};
},
updateCounter: function () {
this.state.some.rather.deeply.embedded.stuff++;
this.setState({}); // just to trigger the render ...
},
render: function() {
return (
<div>
Counter value: {this.state.some.rather.deeply.embedded.stuff}
<br></br>
<button onClick={this.updateCounter}>inc</button>
</div>
);
}
});
export default App;
const React=require('React');
const App=React.createClass({
getInitialState:函数(){
返回{
一些:{
而是:{
深深地:{
嵌入式:{
资料:1
}}}}};
},
updateCounter:函数(){
this.state.some.property.deep.embedded.stuff++;
this.setState({});//只是为了触发渲染。。。
},
render:function(){
返回(
计数器值:{this.state.some.pretty.deep.embedded.stuff}
股份有限公司
);
}
});
导出默认应用程序;
我完全支持以下约定,但我想进一步了解ReactJS实际上是如何工作的,以及上面的代码会出现什么问题或是次优
下面的注释基本上确定了两个问题:
如果您直接对状态进行变异,然后随后调用this.setState
,则可能会替换(覆盖?)您所做的变异。在上面的代码中,我看不出这是如何发生的
setState
可能以异步/延迟的方式有效地变异this.state
,因此在调用this.setState
后立即访问this.state
时,不能保证访问最终的变异状态。我明白了,如果this.setState
是update函数的最后一次调用,那么这不是问题
可以这样说:
切勿直接对该状态进行变异,因为之后调用setState()
可能会替换您进行的变异。将此.state
视为是不可变的
setState()
不会立即改变此.state,但会创建挂起的状态转换。调用此方法后访问this.state
,可能会返回现有值
无法保证对setState
的调用的同步操作,并且可能会对调用进行批处理以提高性能
setState()
将始终触发重新渲染,除非在shouldComponentUpdate()
中实现了条件渲染逻辑。如果正在使用可变对象,并且逻辑无法在shouldComponentUpdate()
中实现,则仅当新状态与以前状态不同时调用setState()
将避免不必要的重新渲染
基本上,如果您直接修改this.state
,就会造成这些修改可能被覆盖的情况
与您的扩展问题1)和2)相关,setState()
不是即时的。它根据它认为正在发生的情况对状态转换进行排队,其中可能不包括对this.state
的直接更改。由于它是排队的,而不是立即应用的,所以完全有可能在这两者之间修改了某些内容,从而覆盖了您的直接更改
如果没有其他问题,您最好考虑不直接修改this.state
可以被视为良好实践。您个人可能知道,您的代码与React的交互方式不会出现这些过度编写或其他问题,但您正在创建一种情况,其他开发人员或未来的更新可能会突然发现自己有奇怪或微妙的问题。我目前的理解基于以下内容:
如果您没有使用应组件更新
或任何其他生命周期方法(如组件将接收道具
,组件将更新
,以及组件更新
)来比较新旧道具/状态
然后
改变状态
,然后调用setState()
,这样做很好,否则就不好。这个答案是为了提供足够的信息,不直接在React中改变/改变状态。
反应如下。也就是说,react内部的数据流应该并且将被预期为循环路径
React的无流量数据流
为了使React像这样工作,开发人员让React类似于函数式编程。函数式编程的经验法则是不变性。让我解释清楚
单向流是如何工作的?
状态
是包含组件数据的数据存储
- 组件的
视图
基于状态进行渲染
- 当
视图
需要更改屏幕上的某些内容时,该值应该由存储提供
- 为了实现这一点,React提供了
setState()
函数,该函数接收新状态的对象
,并对以前的状态进行比较和合并(类似于object.assign()
),并将新状态添加到状态数据存储中
- 每当状态存储区中的数据发生更改时,react将触发重新呈现
视图使用的新状态,并将其显示在屏幕上
该循环将在组件的整个寿命期内持续
如果您看到上面的步骤,它清楚地显示了当您更改状态时许多事情正在发生。因此,当您直接改变状态并使用
// same as
this.state.a.push(6)
this.setState({})
// original state
this.state = {
a: [1,2,3,4,5]
}
// changing the state in react
// need to add '6' in the array
// create a copy of this.state.a
// you can use ES6's destructuring or loadash's _.clone()
const currentStateCopy = [...this.state.a]
currentStateCopy.push(6)
this.setState({
a: currentStateCopy
})
import update from 'immutability-helper';
const newData = update(myData, {
x: {y: {z: {$set: 7}}},
a: {b: {$push: [9]}}
});