Reputation: 83
I am fairly new to react and I have been taking apart a web application and replacing parts with react components. I am now working on a component that holds a few of the different components that I created.
In the new component I make an API call in the componentDidMount function and create the children components. At first glance everything looks perfect, but when we make a state change in one of the child components then make a change in the parent component the children components reset their state to how they were before the changes.
I understand whats going on that the state isn't being passed to the parent, but I'm not sure if there a design for this that I am just missing or if I need to move to a redux store to make this work
class Frame extends Component{
constructor(props){
super(props);
this.state = {
tab: "tab1",
tab1: null,
tab2: null,
}
}
componentDidMount() {
let data = this.props.service.getData();
let tab1 = (<Tab1 {...data} />);
let tab2 = (<Tab2 {...data} />);
this.setState({tab1:tab1, tab2:tab2});
}
render(){
if (!this.state.tab1 || !this.state.tab2){
return (<div>Loading</div>)
}
return (
<ul>
<li onClick={()=>{this.setState({tab:"tab1"})}}></li>
<li onClick={()=>{this.setState({tab:"tab2"})}}></li>
<ul>
<div>
{this.state.tab === "tab1" &&
this.state.tab1
}
{this.state.tab === "tab2" &&
this.state.tab2
}
</div>
)
}
}
Upvotes: 0
Views: 172
Reputation: 83
axnyff, comment was the solution. The if would instantiate the object again in render since it wasn't there before. If I used a css class to hide them they will only be instantiated once since
class Frame extends Component{
constructor(props){
super(props);
this.state = {
tab: "tab1",
tab1: null,
tab2: null,
}
}
componentDidMount() {
let data = this.props.service.getData();
let tab1 = (<Tab1 {...data} />);
let tab2 = (<Tab2 {...data} />);
this.setState({tab1:tab1, tab2:tab2});
}
render(){
if (!this.state.tab1 || !this.state.tab2){
return (<div>Loading</div>)
}
return (
<ul>
<li onClick={()=>{this.setState({tab:"tab1"})}}></li>
<li onClick={()=>{this.setState({tab:"tab2"})}}></li>
<ul>
<div>
<div class=> {this.state.tab !== "tab1" && "hidden"}>
{this.state.tab1}
</div>
<div class=> {this.state.tab !== "tab2" && "hidden"}>
{this.state.tab2}
</div>
</div>
)
}
}
Upvotes: 1
Reputation: 1014
componentDidMount
works only once.class Frame extends Component {
constructor(props) {
super(props);
this.state = {
tab: 'tab1',
data: null,
};
}
componentDidMount() {
let data = this.props.service.getData();
if (data) {
this.setState({ data });
}
}
render() {
if (this.state.data) {
return <div>Loading</div>;
}
return (
<div>
<ul>
<li
onClick={() => {
this.setState({ tab: 'tab1' });
}}
/>
<li
onClick={() => {
this.setState({ tab: 'tab2' });
}}
/>
</ul>
<div>
{this.state.tab === 'tab1' && <Tab {...this.state.data} />}
{this.state.tab === 'tab2' && <Tab {...this.state.data} />}
</div>
</div>
);
}
}
Upvotes: 0
Reputation: 1241
Write a click handler that sets state, and call it onClick rather than setting state directly in render.
Upvotes: 0