我希望这个开关可以工作,但不知何故,组件<A/>
的构造函数只被调用了一次。 https://codesandbox.io/s/jvr720mz75
import React, { Component } from "react";
import ReactDOM from "react-dom";
class App extends Component {
state = { toggle: false };
render() {
const { toggle } = this.state;
return (
<div>
{toggle ? <A prop={"A"} /> : <A prop={"B"} />}
<button onClick={() => this.setState({ toggle: !toggle })}>
toggle
</button>
</div>
);
}
}
class A extends Component {
constructor(props) {
super(props);
console.log("INIT");
this.state = { content: props.prop };
}
render() {
const { content } = this.state;
return <div>{content}</div>;
}
}
ReactDOM.render(<App />, document.getElementById("root"));
我已经找到了 https://codesandbox.io/s/0qmnjow1jw 解决方法。
<div style={{ display: toggle ? "none" : "block" }}>
<A prop={"A"} />
</div>
<div style={{ display: toggle ? "block" : "none" }}>
<A prop={"B"} />
</div>
我想了解为什么上面的代码不起作用
在 react 中,如果您想多次渲染相同的组件并将它们视为不同组件,那么您需要为它们提供一个独特的key
。请尝试以下代码。
{toggle ? <A key="A" prop={"A"} /> : <A key="B" prop={"B"} />}
由于该三元语句在任何一种情况下都会呈现一个<A>
组件的结果,当<App>
的状态更新并更改toggle
时,React 看到在和以前相同的位置仍然有一个<A>
,但具有不同的prop
道具。当 React 重新渲染时,它通过尽可能少地进行更改来实现。因此,由于这是同一类元素在同一个地方,因此 React 不需要在toggle
更改时创建新元素,只需更新该<A>
元素的 props。
从本质上讲,这条线
{toggle ? <A prop="A"/> : <A prop="B"/> }
相当于
<A prop={ toggle ? "A" : "B" }/>
也许更清楚地不需要创建新的<A>
组件,只需更新现有组件。
那么问题就变成了您在构造函数中使用props.prop
设置<A>
的state.content
,因此state.content
永远不会更新。解决此问题的最干净方法是在<A>
组件的render
方法中使用props.prop
而不是state.content
。因此,您的A
类如下所示:
class A extends Component {
render() {
const { prop } = this.props;
return <div>{ prop }</div>;
}
}
如果必须获取prop
道具并在<A>
组件的状态下使用它,则可以使用componentDidUpdate
.下面是一个示例:
class A extends Component {
constructor(props) {
super(props);
this.state = {content: props.prop};
}
componentDidUpdate(prevProps) {
if (prevProps.prop !== this.props.prop) {
this.setState({content: this.props.prop});
}
}
render() {
const { content } = this.state;
return <div>{ content }</div>
}
}
React 只会调用构造函数一次。这是预期的结果。 看起来您正在尝试根据道具更新组件 A 的状态。 你可以直接使用prop,也可以使用componentDidUpdate生命周期方法,正如Henry所建议的那样。另一种方法是使用静态方法 getDerivedStateFromProps 根据传递的 prop 更新状态。
static getDerivedStateFromProps(props, state) {
return ({
content: props.prop
});
}