Вот рабочая версия.
class App extends React.Component {
state = {
items: [ "Pumpkin Pie", "Spaghetti", "Onion Pie" ],
ingredients: [
[ "Pumpkin Puree", "Sweetened Condensed Milk", "Eggs", "Pumpkin Pie Spice", "Pie Crust" ],
[ "Noodles", "Tomatoe", "Sauce", "Meatballs" ],
[ "Onion", "Pie Crust" ],
],
}
render() {
return (
<div className="box">
<Item items={this.state.items} ingredients={this.state.ingredients} />
</div>
);
}
}
const Item = props => (
<div>
<div className="Recipe-Item-Container" key={props.text}>
{props.items.map( ( item, index ) => (
<div className="Recipe-Item" key={item}>
<h3>{item}</h3>
<ul>
{
props.ingredients[ index ].map( ingredient =>
<li key={ingredient}>{ingredient}</li> )
}
</ul>
<div className="buttons-container">
<button className="edit-button" onClick={() => props.edit( item, index )}>Edit</button>
<button className="delete-button" onClick={() => props.delete( item, index )}>Delete</button>
</div>
</div>
) )}
</div>
</div>
);
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Но на вашем месте я бы изменил форму своего состояния.Примерно так:
class App extends React.Component {
state = {
items: [
{
name: "Pumpkin Pie",
ingredients: [
"Pumpkin Puree",
"Sweetened Condensed Milk",
"Eggs",
"Pumpkin Pie Spice",
"Pie Crust"
]
},
{
name: "Spaghetti",
ingredients: ["Noodles", "Tomatoe", "Sauce", "Meatballs"]
},
{
name: "Onion Pie",
ingredients: ["Onion", "Pie Crust"]
}
]
};
removeItem = item => {
const newItems = this.state.items.filter(el => el.name !== item.name);
this.setState({ items: newItems });
};
editItem = item => alert(`${item.name} will be edited`);
renderItems = () =>
this.state.items.map(item => (
<Item
key={item.name}
item={item}
removeItem={this.removeItem}
editItem={this.editItem}
/>
));
render() {
return <div className="box">{this.renderItems()}</div>;
}
}
const Item = props => {
const { item, removeItem, editItem } = props;
const handleRemove = () => removeItem(item);
const handleEdit = () => editItem(item);
return (
<div>
<div className="Recipe-Item-Container" key={props.text}>
<div className="Recipe-Item">
<h3>{item.name}</h3>
<ul>
{item.ingredients.map(ingredient => (
<li key={ingredient}>{ingredient}</li>
))}
</ul>
<div className="buttons-container">
<button className="edit-button" onClick={handleEdit}>
Edit
</button>
<button className="delete-button" onClick={handleRemove}>
Delete
</button>
</div>
</div>
</div>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Изменения
- Форма состояния: Вместо удержания двух массивов мы сохраняем объект для каждого элемента,Этот объект имеет свойства
name
и ingredients
.Может быть, в будущем у него может появиться уникальный id
?Объекты являются гибкими. - Вместо того, чтобы передавать все элементы в компонент
Item
, мы сопоставляем элементы в родительском компоненте и передаем только один элемент компоненту Item
. - У нас все еще есть функции-обработчики, определенные в родительском.Но мы не используем их непосредственно в обратном вызове кнопки с помощью функции стрелки.Таким образом, они не воссоздаются в каждом рендере.Кроме того, нам не нужно использовать индекс для передачи элементов обратно родителю.У нас есть
item
сама опора!Вы можете увидеть, как мы обрабатываем функцию удаления: с помощью .filter
Вы можете применить ту же функцию к другим функциям..map
, .filter
, Object.assign
или распространенный синтаксис - все это хорошие инструменты.Просто избегайте прямого изменения своего состояния.