Динамически управлять состоянием строк в react-table

Вопрос или проблема

Данные колонок, которые мемоизированы

const Columns = useMemo(() => {
    return {
        // некоторые колонки
      comments: {
        Header: "Комментарии",
        accessor: "comments",
        width: "250",
        Cell: (props) => {
          const index = props.row.index
          const comments = props.data[index].comments || []
          const orderID = props.data[index].id || ""

          const onCommentChange = (comment : string) => {
            setOrders(getRefreshedOrdersForComments(orders, orderID, comment))
          }

          return 

                <LatestComment
                  comments={
                    comments.latest_comment ? [comments.latest_comment] : []
                  }
                  count={comments.no_of_comments}
                  orderID={orderID}
                  successCallback={onCommentChange}
                  orders={editOrder}
                />

        },
      }, // некоторые колонки
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [orderID, orders])

Компонент таблицы

<Table
    data={orders}
    columns={columns}
 />

Компонент комментария, который имеет список orders из таблицы, а orderID предназначен для отдельной строки.

const comment= ({ comments, orders, orderId }) => {
   const [editMode, setEditMode] = useState(false)
   const onAdd = useCallback((e) => {
     e.stopPropagation()
     setEditMode(true)
   }, [orderID])
   return {editMode && (
            <CommentEditor
              comment={""}
              onCancel={(e) => onCancel(e)}
              onSave={onSave}
              awaitingStatus={awaitingResponse || ""}
            />
          )}
          {isWriteAllowed && (
                  <div
                    data-testid="latest-comment-add-new"
                    className={`${Styles["comment-edit"]} ignore_row_click`}
                    onClick={onAdd}
                  >
                    Добавить
                  </div>
                )}
}

При нажатии на кнопку добавления открывается окно комментария, но когда я нажимаю следующую кнопку добавления, предыдущее окно комментария все еще открыто. Что с этим делать? Пробовал много вещей, ничего не работает. Проблема в том, что мы используем reactTable V7.

Ответ или решение

Управление состоянием для строк в react-table

При использовании react-table, особенно версии 7, возникает необходимость динамического управления состоянием строк, что может быть вызвано созданием таких компонентов, как редакторы комментариев, которые должны открываться и закрываться в зависимости от действий пользователя. В данной статье мы рассмотрим, как эффективно решать эту проблему, чтобы избежать конфликтов при управлении состоянием разных строк.

Проблема

Проанализировав ваш код, мы видим, что при нажатии на кнопку "Добавить" открывается редактор комментариев. Однако при нажатии на кнопку "Добавить" в другой строке редактор комментариев предыдущей строки остаётся открытым. Это связано с тем, что состояние открытости редактора комментариев не привязано к конкретной строке данных.

Решение

Чтобы исправить эту ситуацию, можно воспользоваться массивом состояний, где для каждой строки будет храниться индивидуальное состояние (открыт или закрыт). Для этого можно использовать массив с использованием индексов строк или объект, где ключами будут идентификаторы строк (orderID).

Шаги к реализации

  1. Создание состояния: Создайте массив состояний для отслеживания, открыты ли редакторы комментариев для каждой строки.

  2. Управление состоянием: Для каждой строки в таблице создайте функцию, которая будет записывать новое состояние и закрывать все другие редакторы.

  3. Передача состояния: Обновите ваши компоненты, чтобы они реагировали на изменения состояния, открывая или закрывая редакторы в зависимости от общего состояния.

Пример реализации

Вот как можно реализовать предложенные шаги:

const [openEditors, setOpenEditors] = useState({});

// Функция для управления открытием и закрытием редакторов
const toggleEditor = useCallback((orderId) => {
    setOpenEditors(prevState => ({
        ...prevState,
        [orderId]: !prevState[orderId] // Переключаем состояние для конкретного orderId
    }));
}, []);

// Обновленный компонент комментариев
const Comment = ({ comments, orders, orderId }) => {
    const isEditMode = openEditors[orderId] || false;

    return (
        <>
            {isEditMode && (
                <CommentEditor
                    comment={""}
                    onCancel={() => toggleEditor(orderId)} // Закрываем редактор
                    onSave={onSave}
                />
            )}
            {isWriteAllowed && (
                <div
                    className={`${Styles["comment-edit"]} ignore_row_click`}
                    onClick={() => toggleEditor(orderId)} // Открываем/закрываем редактор
                >
                    Add
                </div>
            )}
        </>
    );
};

Заключение

Подобный подход позволяет удобно управлять состоянием редакторов, избегая конфликтов между разными строками. Обратите внимание на то, что состояние открытости редакторов комментариев теперь привязано к уникальному идентификатору каждой строки. При этом, можно наблюдать, как простое управлением состоянием может значительно улучшить пользовательский опыт и сделать интерфейс более интуитивно понятным.

Таким образом, динамическое управление состоянием в react-table возможно с использованием вложенных состояний и правильной архитектуры компонентов. Эти изменения не только решают текущую проблему, но и делают код более читаемым и поддерживаемым в будущем.

Оцените материал
Добавить комментарий

Капча загружается...