ES6类处于状态的ReactJS:只更改一次
ReactJS with ES6 class in state: change only once
我对ReactJS完全陌生,当我创建计数器应用时,有一点奇怪的行为
https://jsfiddle.net/8f5tqr74/2/
class CounterViewModel {
constructor() {
this.value = 5;
}
tick() {
//cannot move logic of this method to sendTick complex logic will be here
this.value++;
}
}
var Counter = React.createClass({
getInitialState: function () {
return new CounterViewModel();
},
sendTick: function () {
console.log("Before:",this.state);
var stateObj = this.state;
stateObj.tick();
this.setState(stateObj);
console.log("After:",this.state);
},
render: function () {
return <div>
{this.state.value}
<button onClick={this.sendTick}>Increase</button>
</div>
}
});
ReactDOM.render(<Counter />, document.getElementById('container'));
我的问题是此代码仅在我第一次单击按钮时有效在开发者控制台中得到这个之后
//first click
Before: CounterViewModel {value: 5}
After: CounterViewModel {value: 6}
//second click
Before: Object {value: 6}
在第二次点击中,状态类被刷新到Object,但我没有在这个对象中进行操作
我的问题是:
1) 为什么React在setState之后刷新对象的类?
2) 为什么React不在getInitialState之后刷新类对象?
3) 如何在React中将复杂的逻辑放入状态对象?我知道我可以用增加的值重新创建对象,一切都会很好地工作(见下面的代码)
class CounterViewModel {
constructor(value) {
this.value = value;
}
}
var Counter = React.createClass({
getInitialState: function () {
return new CounterViewModel(5);
},
sendTick: function () {
this.setState(new CounterViewModel(this.state.value+1))
},
render: function () {
return <div>
{this.state.value}
<button onClick={this.sendTick}>Increase</button>
</div>
}
});
ReactDOM.render(<Counter />, document.getElementById('container'));
React期望state
是一个普通的JS对象,这就是为什么在调用setState()
后它会变成对象的原因。
此外,setState
不会立即突变this.state
,这意味着当它打印在代码中时
After: CounterViewModel {value: 6}
state
并没有真正改变,如果你像这个jsfiddle一样将console.log()移动到setState
的回调函数中,你会注意到在状态改变后,state
变成了一个普通对象
Before: CounterViewModel {value: 5}
After: Object {value: 6}
那么你该怎么解决呢
您使用了一个普通对象作为state
,并且必须将其视为一个不可变的对象。
var Counter = React.createClass({
getInitialState: function () {
return {counter: new CounterViewModel()}
},
sendTick: function () {
var stateObj = Object.assign(new CounterViewModel(),this.state.counter); // Deep clone
stateObj.tick();
this.setState({counter: stateObj});
},
render: function () {
console.log(this.state);
return <div>
{this.state.counter.value}
<button onClick={this.sendTick}>Increase</button>
</div>
}
});
工作jsfiddle
QoP是正确的,React希望状态是一个普通的JavaScript对象。我的答案与他/她的不同之处在于,我没有将CounterViewModel
实例复制到组件的状态。
像你这样使用单独的类是很麻烦的,所以与它交互会有点难看。为什么在其他代码中使用class
语法,而在React组件中使用旧的React语法?
import {Component} from 'react'
class Counter extends Component {
constructor (props) {
// call parent constructor
super(props)
// create an instance of counter view model
// save it as a normal instance property (not the same as `this.props`)
this.counter = new CounterViewModel()
// set initial state using the instance's counter value
// do NOT copy the counter object directly to state
this.state = { counter: this.counter.value }
}
sendTick (event) {
// mutate your counter object
this.counter.tick()
// set the component state with the counter's value
this.setState({ counter: this.counter.value })
}
render () {
return (
<div>
{this.state.value}
// note the slight difference in the way I set onClick
// read more: https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#autobinding
<button onClick={e=> this.sendTick(e)}>Increase</button>
</div>
)
}
}
export default Counter
相关文章:
- Javascript返回值只在循环中返回一次
- Jquery FadeIn FadeOut 只工作一次
- Javascript html每点击一次就会更改url
- React Js 组件在状态更改后只渲染一次
- Javascript:onclick函数工作一次,页面就会恢复到原来的状态
- SlideJS隐藏仅适用于一次
- jQuery表单验证只适用于一次发布
- 推送状态仅工作一次
- 如何只运行一个函数一次,然后运行另一个依赖于相同元素的函数
- JavaScript 和 radio_button in rails - 状态只检查一次
- 确保一次只运行一个 setTimeout(处于活动状态)
- Javascript-只用于循环打印最后一次迭代
- 修改父状态的子状态“一次点击”
- 使用java脚本显示最后一次看到的网页状态
- 函数只适用于最后一次调用
- 如何用history.js捕获一次状态改变事件
- 如何使用JavaScript每10秒检查一次状态
- ES6类处于状态的ReactJS:只更改一次
- 一次只将 jquery 脚本应用于一个类
- iPad上的响应式设计只适用于一次