React 组件仅在第二个 onClick 事件上更改状态
React component only changes state on second onClick event
我有这两个 简化的 React 组件,其中 Times
组件是 Create
组件的子组件(代码示例见下文)。预期的行为是,最初未显示 Times
组件,但当用户单击带有 onClick
的 link 时,会出现 Times
组件。
这些组件大部分都按预期工作,但奇怪的是,在第一次单击 onClick
link 后,Times
组件没有出现并且 Create
组件根本没有改变状态,如控制台所示。但是,当第二次单击 link 时,Create
组件确实会更改状态并重新呈现,并且会看到 Times
组件。
Create.jsx
import React from 'react';
import Times from './Times.jsx';
export default React.createClass({
getInitialState: function () {
return {times: false};
},
_change: function () {
this.replaceState({times: true});
console.log(this.state.times);
},
render: function () {
return (
<div id="create">
<div id="outerbox">
<a onClick={this._change}>Times</a>
<Times shouldShow={this.state.times}/>
</div>
</div>
);
}
});
Times.jsx
import React from 'react';
export default React.createClass({
propTypes: {
shouldShow: React.PropTypes.bool.isRequired
},
getDefaultProps: function () {
return {shouldShow: false};
},
getInitialState: function () {
return {el: 'times'};
},
componentDidMount: function() {
if (this.props.shouldShow === false) {
this.setState({display: 'none'});
} else {
this.setState({display: 'block'});
}
},
componentWillReceiveProps: function() {
if (this.props.shouldShow === false) {
this.setState({display: 'none'});
} else {
this.setState({display: 'block'});
}
},
render: function () {
return (
<div id={this.state.el} style={{"display": this.state.display}}>
<h1>Times</h1>
</div>
);
}
});
console.log
的输出
false
true
为什么 Create
组件的状态在第一次点击时没有被注册?
问题就在这里
componentWillReceiveProps: function() {
if (this.props.shouldShow === false) {
this.setState({display: 'none'});
} else {
this.setState({display: 'block'});
}
}
应该是,
componentWillReceiveProps: function(newProps) {
if (newProps.shouldShow === false) {
this.setState({display: 'none'});
} else {
this.setState({display: 'block'});
}
}
ComponentWillRecieveProps 是组件 class 的成员函数,它在 props "applied" 之前被调用。这意味着 this.props
是旧的 Props。您应该使用作为参数提供给函数的 newProps
。
http://codepen.io/bhargav175/pen/gaJmKz
另外,我感觉你使用的状态比你需要的多了一点。您根本不需要将显示作为状态变量。 Times 是一个内部组件,因此尽可能使用 props 并使其无状态是有意义的。
围绕 "props change don't affect the render, so lets use state" 有一个普遍的误解。道具在重新渲染时也会改变结果,所以除非有充分的理由并且您确实需要使内部组件智能化,否则请始终使用道具。在内部组件中使用 props,使它们变笨并且更易于使用。
http://codepen.io/bhargav175/pen/WQBpzP
var Times = React.createClass({
propTypes: {
shouldShow: React.PropTypes.bool.isRequired
},
getDefaultProps: function () {
return {shouldShow: false};
},
getInitialState: function () {
return {el: 'times'};
},
render: function () {
let display = this.props.shouldShow ? "block" : "none";
return (
<div id={this.state.el} style={{"display": display}}>
<h1>Times</h1>
</div>
);
}
});
我有这两个 简化的 React 组件,其中 Times
组件是 Create
组件的子组件(代码示例见下文)。预期的行为是,最初未显示 Times
组件,但当用户单击带有 onClick
的 link 时,会出现 Times
组件。
这些组件大部分都按预期工作,但奇怪的是,在第一次单击 onClick
link 后,Times
组件没有出现并且 Create
组件根本没有改变状态,如控制台所示。但是,当第二次单击 link 时,Create
组件确实会更改状态并重新呈现,并且会看到 Times
组件。
Create.jsx
import React from 'react';
import Times from './Times.jsx';
export default React.createClass({
getInitialState: function () {
return {times: false};
},
_change: function () {
this.replaceState({times: true});
console.log(this.state.times);
},
render: function () {
return (
<div id="create">
<div id="outerbox">
<a onClick={this._change}>Times</a>
<Times shouldShow={this.state.times}/>
</div>
</div>
);
}
});
Times.jsx
import React from 'react';
export default React.createClass({
propTypes: {
shouldShow: React.PropTypes.bool.isRequired
},
getDefaultProps: function () {
return {shouldShow: false};
},
getInitialState: function () {
return {el: 'times'};
},
componentDidMount: function() {
if (this.props.shouldShow === false) {
this.setState({display: 'none'});
} else {
this.setState({display: 'block'});
}
},
componentWillReceiveProps: function() {
if (this.props.shouldShow === false) {
this.setState({display: 'none'});
} else {
this.setState({display: 'block'});
}
},
render: function () {
return (
<div id={this.state.el} style={{"display": this.state.display}}>
<h1>Times</h1>
</div>
);
}
});
console.log
的输出false
true
为什么 Create
组件的状态在第一次点击时没有被注册?
问题就在这里
componentWillReceiveProps: function() {
if (this.props.shouldShow === false) {
this.setState({display: 'none'});
} else {
this.setState({display: 'block'});
}
}
应该是,
componentWillReceiveProps: function(newProps) {
if (newProps.shouldShow === false) {
this.setState({display: 'none'});
} else {
this.setState({display: 'block'});
}
}
ComponentWillRecieveProps 是组件 class 的成员函数,它在 props "applied" 之前被调用。这意味着 this.props
是旧的 Props。您应该使用作为参数提供给函数的 newProps
。
http://codepen.io/bhargav175/pen/gaJmKz
另外,我感觉你使用的状态比你需要的多了一点。您根本不需要将显示作为状态变量。 Times 是一个内部组件,因此尽可能使用 props 并使其无状态是有意义的。
围绕 "props change don't affect the render, so lets use state" 有一个普遍的误解。道具在重新渲染时也会改变结果,所以除非有充分的理由并且您确实需要使内部组件智能化,否则请始终使用道具。在内部组件中使用 props,使它们变笨并且更易于使用。
http://codepen.io/bhargav175/pen/WQBpzP
var Times = React.createClass({
propTypes: {
shouldShow: React.PropTypes.bool.isRequired
},
getDefaultProps: function () {
return {shouldShow: false};
},
getInitialState: function () {
return {el: 'times'};
},
render: function () {
let display = this.props.shouldShow ? "block" : "none";
return (
<div id={this.state.el} style={{"display": display}}>
<h1>Times</h1>
</div>
);
}
});