Изменение cостояния конкретной кнопки по нажатию. ReactJS

читатель! Ниже предоставлю отрывки кода для большей ясности.

Ниже в стейте хранятся некоторые свойства, которые будут упоминаться дальше.

state = {
        dataArr: [], // Массив полученых данных с сервера
        divShow: false,
        name: '',
        age: '',
        email: '',
        btnEditShow: true,
        // btnSaveShow: false,
        idData: '',
        // btnEditBool: true
    };

Здесь представлен весь фрагмент рендеринга и тут же имеется проблема, которую я опишу ниже(после кода).

render() {
        const { dataArr, divShow, btnEditShow, btnSaveShow, btnEditBool } = this.state

        return (
            <div className='containerTableBack' >

                <table className="table tableBack" border="1">
                    <caption>Here is data backEnd:</caption>
                    <thead>
                        <tr>
                            <th>Name</th>
                            <th>Age</th>
                            <th>Email</th>
                        </tr>
                    </thead>
                    <tbody>
                        {dataArr.map(e => {
return (  <tr key={e}><td>{e.data.name}</td><td>{e.data.age}</td><td>{e.data.email}</td>
<td> <button
                                        key={e}
                                        id={e._id}
                                        className={btnEditShow ? '' : 'btnEditShow'}
                                        // style={btnEditShow ? {} : { display: 'none' }}
                                        onClick={this.btnShowEditInputs}
                                    >Edit</button></td>
                                    <button
                                        id={e._id}
                                        onClick={this.deleteData}
                                    >Delete</button> </tr>
                            );
})}
                    </tbody>
                </table>

                <div className={`newData-Div ${!divShow ? 'displayDivNone' : ''} `} >
                    <input placeholder="Name" type='text' onChange={this.nameHandleChange} />
                    <input placeholder="Age" type='number' onChange={this.ageHandleChange} />
                    <input placeholder="Email" type='text' onChange={this.emailHandleChange} />
                    <button onClick={this.addNoteOnPage} >Add Note</button>
                </div>

                <button onClick={this.addNewData} >Add Note</button>

            </div>
        );
    }

Функция, которая используется:

btnShowEditInputs = (e) => {

        this.setState({ btnEditShow: false })
}

Ниже фрагмет с проблемой:

{dataArr.map(e => {
return (
                                <tr key={e}><td>{e.data.name}</td><td>{e.data.age}</td><td>{e.data.email}</td>
<td> <button
                                        key={e}
                                        id={e._id}
                                        className={btnEditShow ? '' : 'btnEditShow'}
                                        // style={btnEditShow ? {} : { display: 'none' }}
                                        onClick={this.btnShowEditInputs}
                                    >Edit</button></td>
                                    <button
                                        id={e._id}
                                        onClick={this.deleteData}
                                    >Delete</button> </tr>
                            );

Сама суть проблемы заключается в следующем. Отрисовывается таблица, т.е. первый компонент(куда входят данные, кнопка edit и delete), второй и последующие компоненты так же с данными и кнопками. Как с помощью стейтов или других способов можно сделать так, при нажатии на кнопку Edit она скрывалась и появлялась кнопка Save? Делал много разных способов, но всегда при нажатии на Edit у меня все кнопки из Edit скрывались, а Save появлялись, а мне нужно только на одной компоненте это сделать.


Ответы (1 шт):

Автор решения: Alexandr Kiseloy

Вам можно вынести строку таблицы в отдельный компонент, со своим стейтом, например:

const TableRow = ({ name, age, email, onEdit, onDelete, onSave }) => {
    const [ isEdit, setIsEdit ] = useState(false);
    const handlerClickEdit = useCallback(() => {
        setIsEdit(true);
        onEdit();
    }, [ onEdit ]);
    const handlerClickSave = useCallback(() => {
        setIsEdit(true);
        onSave();
    }, [ onSave ]);
    return (
        <tr>
            <td>{ name }</td>
            <td>{ age }</td>
            <td>{ email }</td>
            <td>
                {!isEdit && (
                    <button onClick={ handlerClickEdit }>
                        Edit
                    </button>
                )}
                {isEdit && (
                    <button onClick={ handlerClickSave }>
                        Save
                    </button>
                )}
            </td>
            <button
                onClick={ onDelete }
            >Delete
            </button>
        </tr>
    );
}

const Table = () => {
    const data = [ { id: 1, name: 'Test' } ];
    return (
        <table>
            { data.map((item) => (
                <TableRow
                    key={item.id}
                    name={item.name}
                    age={null}
                    email={null}
                    onEdit={() => null}
                    onDelete={() => null}
                    onSave={() => null}
                />
            ))}
        </table>
    )
}

Или хранить в state не флаг, а id записи и при рендере проверять на редактирование. Например:

class Component {
      state = {
        data: [ {id: 1, name: 'Test' }],
        editId: null,
      }
      
      handlerClickEdit = (rowId) => (e) => {
        this.setState({ editId: rowId });
      }
      
      handlerClickSave = (rowId) => (e) => {
        this.setState({ editId: null });
      }
      
      render() {
      const { editId } = this.state;
        return (
          <table>
            {data.map((item) => (
              <tr key={item.id}>
                <td>{ name }</td>
                <td>
                  {item.id === editId && (
                    <button onClick={this.handlerClickSave(item.id)}>
                      Save
                     </button>
                  )}
                  {item.id !== editId && (
                    <button onClick={this.handlerClickEdit(item.id)}>
                      Edit
                     </button>
                  )}
                </td>
              </tr>
            ))}
          <table/>
         
        )
      }
    }

Если есть возможность редактировать сразу несколько записей, то в editId должен быть массив и проверка на вхождение item.id в него.

→ Ссылка