#javascript #reactjs
#javascript #reactjs
Вопрос:
У меня есть компонент, который отображает список элементов с помощью функции map. Каждый элемент отображается с помощью кнопки удаления и редактирования. Я добавил функцию удаления, но у меня возникли проблемы с редактированием.
Функциональность, которую я хочу, такова: нажмите на элемент редактирования, замените элемент H3 (который является заголовком) полем ввода и позвольте пользователю обновить имя. Я пытался заменить элемент другим, но это работает только для первого элемента списка, потому что я получаю элемент с помощью ‘getElementById’ Я пытался сделать это с помощью querySelector, но это выбирает только последний элемент массива.
Я понятия не имею, что делать. Я знаю, что проблема заключается в выборе конкретного элемента с правильным индексом. Я использую идентификатор в качестве ключа, но я не знаю, как правильно заменить элемент html. Любая помощь будет высоко оценена.
Здесь функция отображения отображает элементы:
class Donut extends Component {
render(){
const {donuts, deleteDonut, editDonut} = this.props;
const donutsList = donuts.map((donut) => {
return <div key={donut.id} className="donut">
<div className="name">
<img src={donut.image} />
<div id="donut-name">
<h3 id="donut-title">{donut.name}</h3>
<p>{donut.date}</p>
</div>
</div>
<div className="price">
<p>{donut.price}</p>
<img src="img/edit.png" id={donut.id} onClick={()=>{editDonut(donut.id)}} />
<img src="img/delete.png" id={donut.id} onClick={() => {deleteDonut(donut.id)}} />
</div>
</div>
})
return (
<div>
{donutsList}
</div>
)
}
}
export default Donut
Комментарии:
1. Рассмотрите возможность использования
querySelectorAll
, которое вернет вам список совпадающих элементов. Идентификаторы в HTML должны быть уникальными, поэтомуgetElementById
возвращает один элемент DOM.
Ответ №1:
Старайтесь избегать, насколько это возможно, прямого манипулирования элементами DOM при использовании React. В этом случае вам следует использовать другой подход:
-
Добавьте поле в состояние этого класса:
editingDonutId
-
Когда вы нажимаете на пончик, установите
editingDonutId
соответствующий идентификатор, а когда закончите, сбросьте значение. -
В функции рендеринга, внутри
map
, выполните рендеринг условия, чтобы проверить, имеет ли текущий пончик рендеринга тот же идентификаторeditingDonutId
, если true, вместо этого мы рендерим ввод.
Ответ №2:
Вы используете react, а не jquery, поэтому не используйте getElementById, попробуйте решение react. Это мое решение:
class Donut extends Component {
state = {
donutsState: {}
}
setDonutState: (id, value) => {
this.setState((preState) => {
const predonutState = preState.donutsState[id] || {}
return {
donutsState: {
...preState.donutsState,
[id]: {
...predonutState,
...value,
}
}
}
})
}
getDonutState: (id) => this.state.donutsState[id] || {};
render(){
const {donuts, deleteDonut, editDonut} = this.props;
const donutsList = donuts.map((donut) => {
const donutState = this.getDonutState(donut.id)
// when user input the name, save it in the state.
const onChange = (e) => {
this.setDonutState(donut.id, { value: e.target.value })
}
// when click edit, replace h3 with input.
const onEdit = () => {
this.setDonutState(donut.id, { eidt: true })
}
// when enter key, replace input with h3 and submit the name value.
const onKeyDown = (e) => {
if (e.key === 'Enter') {
this.setDonutState(donut.id, { eidt: false })
editDonut(donut.id, {
name: this.getDonutState(donut.id).value || donut.name,
})
}
}
return (
<div key={donut.id} className="donut">
<div className="name">
<img src={donut.image} />
<div id="donut-name">
{
donutState.edit
? <input id="edit-donut-title" value={donutState.value || donut.name} onChange={onChange} onKeyDown={onKeyDown} />
: <h3 id="donut-title">{donut.name}</h3>
}
<h3 id="donut-title">{donut.name}</h3>
<p>{donut.date}</p>
</div>
</div>
<div className="price">
<p>{donut.price}</p>
<img src="img/edit.png" id={donut.id} onClick={()=>{editDonut(donut.id)}} />
<img src="img/delete.png" id={donut.id} onClick={() => {deleteDonut(donut.id)}} />
</div>
</div>
)
})
return (
<div>
{donutsList}
</div>
)
}
}
export default Donut