I have a CustomReactComponent class which holds a list of similar React Components, I then render a single element Component from the list based on some condition.
This Component has <input/> tag.
When I try to render it all the <input/> tags have the same value when User changes only one of them.
How can I prevent this from happening? and have the inputs store differnt values for each instance
Minimal Reproducible Code:
import {Component} from "react";
export default class CustomReactComponent extends Component {
constructor(props) {
super(props);
this.state = {selected: 0};
this.list = [<div><input/></div>, <div><input/></div>, <div><input/></div>, <div><input/></div>];
}
onSelect = (e) => {
this.setState({selected: e.target.value});
}
render() {
let Component = this.list[this.state.selected];
return (
<div>
<select onChange={this.onSelect}>
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<div>
State:{this.state.selected}:
{Component}
</div>
</div>
);
}
}
Edit 1:
As @asynts pointed out we could use key for each component, but keys's check for siblings during rendering, and since here i am rendering only a single component, key would be of no use, it re-initializes the component every time the state selected changes. But this is a start, it atleast dosent treat all the components in this.list as the same thing
Edit 2:
After some tinkering and experimentation I found a work around for this, we can have a Wrap Component which is given a unique id uid as a prop this can then be used during rendering if state selected points to uid of a Wrap we style it to display: initial else to display: none, this is where key's comes handy we can always render all the siblings and give it a key same as uid
Code:
import {Component} from "react";
function Wrap({uid}) {
return <div>uid = {uid} : <input/></div>
}
export default class CustomReactComponent extends Component {
constructor(props) {
super(props);
this.state = {selected: 0};
this.list = [
<Wrap uid={0}/>,
<Wrap uid={1}/>,
<Wrap uid={2}/>,
<Wrap uid={3}/>
];
}
onSelect = (e) => {
this.setState({selected: parseInt(e.target.value)});
}
render() {
return (
<div>
State:
<select onChange={this.onSelect}>
<option value="0">0</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<div>
{this.list.map((component) =>
<div key={component.props.uid}
style={{display: component.props.uid !== this.state.selected ? 'none' : 'initial'}}>
{component}
</div>)}
</div>
</div>
);
}
}