I have a store which gives me array of password objects For Example :
const passwords = [{
id: 'hjgkjhkjl',
password: 'jhckjdhf',
createdAt: 'jan 3rd, 2019'
},
{
id: 'uygkjhkj',
password: 'kdjhfkjdhf',
createdAt: 'jan 3rd, 2019'
}
]
I can access this passwords in my component as this.props.passwords
I am trying to populate them on UI as a List with button(Update / Confirm) - I am toggling between them using a component level state
Since it is a component level state if I click on one button all the buttons are getting changed
Here is my code
class Passwords extends React.Component {
constructor(props) {
super(props)
this.state = {
disabled: false
}
this.handleUpdate = this.handleUpdate.bind(this)
}
handleUpdate(element) {
// this.context.executeAction(removePassword, element.createdAt)
// this.context.executeAction(fetchPasswords)
this.setState({
disabled: !this.state.disabled,
})
}
render() {
const data = [
{
password: "passwordone",
createdAt: "Jan 2, 2019"
},
{
password: "passwordtwo",
createdAt: "Jan 2, 2019"
}
];
return (
<div>
{data.map((element) => {
return (
<div>
<input value={element.password} disabled={!this.state.disabled}/>
<span style={{marginLeft: "15px"}}> {element.createdAt} </span>
<span style={{marginLeft: "15px"}}>
<button onClick={() => this.handleUpdate(element)}>
{this.state.disabled ? "Confirm" : "Update"}
</button>
</span>
</div>
)
})}
</div>
)
}
}
ReactDOM.render(<Passwords/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'>
</div>
Need a better approach to solve this
Working example is in the following Link
id are unique for the password items - expected result update/confirm need to be toggled only for clicked button
Thanks in advance
As sellmeadog said, you should create a parent component that will contain 2 components. Each component will have its own state, and the parent component will give each child its props. This way each button will have its own state, which means its own "disabled". In general it should look like that:
class PasswordsContainer extends React.Component {
constructor(props) {
super(props);
const data = [
{
password: 'passwordone',
createdAt: 'Jan 2, 2019',
},
{
password: 'passwordtwo',
createdAt: 'Jan 2, 2019',
},
];
this.state = {
disabled: false,
data: data,
};
this.handleUpdate = this.handleUpdate.bind(this);
}
handleUpdate(element) {
// this.context.executeAction(removePassword, element.createdAt)
// this.context.executeAction(fetchPasswords)
this.setState({
disabled: !this.state.disabled,
});
}
render() {
return (
<div>
{this.state.data.map(element => {
return <Password data={element} />;
})}
</div>
);
}
}
class Password extends React.Component {
constructor(props) {
super(props);
this.state = {
disabled: false,
data: this.props.data,
};
this.handleUpdate = this.handleUpdate.bind(this);
}
handleUpdate(element) {
this.setState({
disabled: !this.state.disabled,
});
}
render() {
let element = this.state.data;
return (
<div>
<input value={element.password} disabled={!this.state.disabled} />
<span
style={{
marginLeft: '15px',
}}>
{' '}
{element.createdAt}
</span>
<span
style={{
marginLeft: '15px',
}}>
<button onClick={() => this.handleUpdate(element)}>
{this.state.disabled ? 'Confirm' : 'Update'}
</button>
</span>
</div>
);
}
}
ReactDOM.render(<PasswordsContainer />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'>
</div>
please tell me if something is unclear