ReactJSL Как настроить таргетинг на один элемент в функции отображения с помощью кнопки

#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