Reputation: 121
I'm creating a simple to do app. I store my cards/bulletins in the BulletinsList.js and single bulletin/card in a Bulletin.js.
I'm trying to change "Hello World" (using input in Bulletin.js, by clicking on title and switching it to input) title in first bulletin but nothing works so basically I can't update a property of object stored in array. I'm passing an id of object but it doesn't work as well. Could anyone give me a answer how can I do this?
BulletinList.js
import React, { Component } from 'react';
import Bulletin from '../Bulletin/Bulletin';
class BulletinList extends Component {
state = {
bulletin: [
{
id: 1,
title: 'Hello World',
listOfTasks: ['eat sandwich', 'clean house']
},
{
id: 2,
title: 'Hello Mars',
listOfTasks: ['eat spaghetti', 'go to sleep']
},
],
titleField: '',
descriptionField: ''
}
addEmptyCard = () => {
this.setState({
bulletin: [...this.state.bulletin, {id: this.state.bulletin.length + 1, title: '...', listOfTasks: []}]
})
}
captureInput = (event, id) => {
const specificCard = this.state.bulletin[id - 1];
this.setState(prevState => ({
[specificCard]: {
...prevState.specificCard,
title: event.target.value
}
}))
}
render() {
return(
<div>
<button onClick={this.addEmptyCard}>+</button>
{this.state.bulletin.map((element => {
return <Bulletin
id={element.id}
title={element.title}
list={element.listOfTasks}
captureInput={this.captureInput}/>
}))}
</div>
)
}
}
export default BulletinList;
Bulletin.js
import React, { useState } from 'react';
const Bulletin = ({ id, title, list, captureInput }) => {
const [inputOn, setInputOn] = useState(false);
return(
<div>
{!inputOn ? <h1 onClick={() => setInputOn(!inputOn)}>{title}</h1>
:
<div>
<input type="text" onChange={(event) => captureInput(event, id)}/>
<button onClick={() => setInputOn(!inputOn)}>Change title</button>
</div>}
{list.map(element => {
return <p>{element}</p>
})}
<input type="text" />
</div>
)
}
export default Bulletin;
Upvotes: 0
Views: 58
Reputation: 903
In captureInput
you don't override bulletin
property but create a new one instead using object as an index. One of the proper ways to fix this is:
captureInput = (event, id) => {
const newBulletin = [...this.state.bulletin];
newBulletin[id - 1].title = event.target.value;
this.setState({
bulletin: newBulletin
});
}
I'm creating a new array here using spread syntax and then overwriting title
property of element at given position.
Also, you pass element's id
to Bulletin component and then use it as an index. It will work for now as identifiers are ordered, but it would be better to find real index by iterating the array:
captureInput = (event, id) => {
const elemIndex = this.state.bulletin.findIndex(elem => elem.id === id);
const newBulletin = [...this.state.bulletin];
newBulletin[elemIndex].title = event.target.value;
this.setState({
bulletin: newBulletin
});
}
This way you will be able to remove items without breaking your application.
Upvotes: 1