我希望此切换有效,但是以某种方式只能调用组件<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>
我想了解为什么上面的代码不起作用
答案 0 :(得分:3)
在反应中,如果您想多次渲染相同的组件并将它们视为不同,则需要为其提供唯一的key
。尝试下面的代码。
{toggle ? <A key="A" prop={"A"} /> : <A key="B" prop={"B"} />}
答案 1 :(得分:2)
Since that ternary statement renders results in an <A>
component in either case, when the <App>
's state updates and changes toggle
, React sees that there is still an <A>
in the same place as before, but with a different prop
prop. When React re-renders it does so by making as few changes as possible. So since this is the same class of element in the same place, React doesn't need to create a new element when toggle
changes, only update the props of that <A>
element.
Essentially, the line
{toggle ? <A prop="A"/> : <A prop="B"/> }
is equivalent to
<A prop={ toggle ? "A" : "B" }/>
which perhaps more clearly does not need to create a new <A>
component, only update the existing one.
The problem then becomes that you set the state.content
of the <A>
using props.prop
in the constructor, so the state.content
is never updated. The cleanest way to fix this would be to use props.prop
in the render
method of the <A>
component instead of state.content
. So your A
class would look like this:
class A extends Component {
render() {
const { prop } = this.props;
return <div>{ prop }</div>;
}
}
If you must take the prop
prop and use it in the <A>
component's state, you can use componentDidUpdate
. Here's an example:
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>
}
}
答案 2 :(得分:1)
React will only call the constructor once. That's the expected outcome. Looks like you're trying to update the state of the component A based on the props. You could either use the prop directly or use the componentDidUpdate lifecycle method, as Henry suggested. Another way is using the static method getDerivedStateFromProps to update the state based on the prop passed.
static getDerivedStateFromProps(props, state) {
return ({
content: props.prop
});
}