学习反应所以可能有点不成熟的问题。请考虑以下代码:
class Application extends React.Component {
render() {
return <Container />
}
}
class Container extends React.Component {
constructor(props) {
super(props)
this.state = {
isOn: false
}
this.handleToggle = this.handleToggle.bind(this);
}
handleToggle(on) {
this.setState({
isOn: on
});
}
render() {
return (
<div>
<p>
{this.state.isOn ? 'on' : 'off'}
</p>
<MyButton handleToggle={this.handleToggle} />
</div>
);
}
}
class MyButton extends React.Component {
constructor(props) {
super(props);
this.state = {
pressed: false
}
this.handleButtonToggle = this.handleButtonToggle.bind(this);
}
handleButtonToggle() {
const on = !this.state.pressed
this.setState({
pressed: on
});
this.props.handleToggle(on);
}
render() {
return (
<div>
<button onClick={this.handleButtonToggle}>
{this.state.pressed ? "pressed" : "depressed"}
</button>
</div>
);
}
}
ReactDOM.render(<Application />, document.getElementById('app'));
正如您在当前单击Container中的按钮时所看到的那样handleButtonToggle()
被触发,这会更改按钮本身的状态,然后调用函数来更改父Container的状态。这是React的做法吗?当函数handleButtonToggle
被触发时,容器状态被更改。理想情况下,我希望Container状态直接依赖于MyButton 状态(因为将来可能会有通过handleButtonToggle
设置按钮状态的方法,我不想手动每次状态改变时都要调用this.props.handleToggle
。换句话说,当状态发生变化时,有一种方法可以在按钮组件中执行类似this.props.handleToggle(this.state.pressed)
的操作。
答案 0 :(得分:2)
在查看代码之后,编写Button组件的更好方法是使其成为受控组件。如果容器组件需要保持按下状态,受控按钮组件将从容器组件接收按压状态作为道具。
<MyButton pressed={this.state.pressed} onToggle={this.handleToggle} />
Button组件的render方法应为:
render() {
return (
<div>
<button onClick={this.props.onToggle}>
{this.props.pressed ? "pressed" : "depressed"}
</button>
</div>
);
}
实际的按钮切换将在容器组件的handleToggle方法中完成:
handleButtonToggle() {
let { pressed } = this.state;
pressed = !pressed;
this.setState({
pressed
});
}
答案 1 :(得分:1)
您可以将回调作为第二个参数传递给setState
,也可以在组件上实现componentDidUpdate
以等待状态更改。最小的变化是前者:
handleButtonToggle() {
const on = !this.state.pressed
this.setState({
pressed: on
}, () => {
this.props.handleToggle(on);
});
}
或componentDidUpdate
:
componentDidUpdate(prevProps, prevState) {
if (prevState.on !== this.state.on) {
this.props.handleToggle(this.state.on);
}
}
答案 2 :(得分:-1)
这是一个有效的代码:https://codepen.io/damien-monni/pen/XRwewV。 我尽可能多地保留您的代码,以便您可以专注于真正需要的更改。
您需要创建controlled component。按钮的状态将存储在容器中,并通过props传递给子MyButton组件。
/*
* A simple React component
*/
class Application extends React.Component {
render() {
return <Container />
}
}
class Container extends React.Component {
constructor(props) {
super(props)
this.state = {
isOn: false
}
this.handleToggle = this.handleToggle.bind(this);
}
handleToggle() {
this.setState({
isOn: !this.state.isOn
});
}
render() {
return (
<div>
<p>
{this.state.isOn ? 'on' : 'off'}
</p>
<MyButton pressed={this.state.isOn} handleToggle={this.handleToggle} />
</div>
);
}
}
class MyButton extends React.Component {
constructor(props) {
super(props);
this.state = {
pressed: this.props.pressed
}
this.handleButtonToggle = this.handleButtonToggle.bind(this);
}
handleButtonToggle() {
this.props.handleToggle();
}
componentWillReceiveProps(nextProps) {
if (nextProps.pressed !== this.props.pressed) {
this.setState({ pressed: nextProps.pressed });
}
}
render() {
return (
<div>
<button onClick={this.handleButtonToggle}>
{this.state.pressed ? "pressed" : "depressed"}
</button>
</div>
);
}
}
/*
* Render the above component into the div#app
*/
ReactDOM.render(<Application />, document.getElementById('app'));
您需要这样做,因为您想要在两个组件之间共享状态。这是documented here。
我让你看看codepen并询问你的问题。 ;)