React — функция не выводит текущие состояния

#javascript #reactjs #fluent-ui

#javascript #reactjs #fluent-пользовательский интерфейс

Вопрос:

Играя с Fluent UI DetailsList, я создал это решение. Я удалил все ненужные строки, чтобы минимизировать проблему, поскольку кажется, что при входе в onColumnClick систему каким-то образом выводится не текущее состояние, а начальное, почему это происходит:

 import * as React from 'react';
export const ClvKkcgListyHistorie = (props: IClvKkcgListyHistorieWebPartProps) => {
const [notifications, setNotifications] = React.useState<INotificationDetailsList[]>([]);
const [columns, setColumns] = React.useState<IColumn[]>();

React.useEffect(() => {
  setColumns(createColumns(onTitleClick, onColumnClick));
}, []);

// With this useEffect everything works fine
React.useEffect(() => {
  setColumns(createColumns(onTitleClick, onColumnClick));
}, [notifications]);

React.useEffect(() => {
  const fetchAllNotifications = async () => {
   // Fetch items here
  }
  fetchAllNotifications();
}, [])


const onColumnClick = (e: any, column: IColumn) => {
  console.log(notifications,columns, "1" ); 
  // Here I get [], undefined, "1"
}

return (
  <>
  {notifications.length !== 0 amp;amp; 
    <DetailsList 
      items={notifications} 
      columns={columns}
    >
    </DetailsList>
  }
  </>
);
}
 

Columns.tsx

 import * as React from 'react';


export const createColumns = (onTitleClick: any, onColumnClick: any) : IColumn[] => {
  return [
    {
      key: "title", 
      name: "Nadpis", 
      minWidth: 70,
      maxWidth: 100,
      isResizable: true,
      isRowHeader: true,
      isSorted: false,
      isSortedDescending: false,
      sortAscendingAriaLabel: 'A - Z',
      sortDescendingAriaLabel: 'Z - A',
      isPadded: true,
      onColumnClick: onColumnClick,
      onRender: (item: INotificationDetailsList) => {
        return <span>{item.Title}</span>;
      }
    },

    }
  ]
} 
 

В этом

Ответ №1:

Когда вы визуализируете свой компонент, он создает эту функцию onColumnClick и смотрит, какие столбцы находятся в данный момент. Он передает эту функцию в обработчики, запоминая, что это были за столбцы. (В вашем случае пустой массив.)

Чтобы обновить функцию при обновлении столбцов, вам необходимо использовать useCallback . Это аналогично шаблону useEffect , но возвращает функцию вместо запуска функции при изменении зависимостей.

 const onColumnClick = React.useCallback((e: any, column: IColumn) => {
  console.log(notifications,columns, "1" ); 
  // This will return a different function to the handlers
  // whenever columns changes, but not notifications
}, [columns])
 

Комментарии:

1. Как я могу сказать, что он создает функцию, которая «запоминает» состояние во время передачи? Чем это отличается от обычного обратного вызова? Я просто никогда не сталкивался с подобной функцией, «классические» обратные вызовы работают нормально каждый раз 🙂 РЕДАКТИРОВАТЬ: я имею в виду, откуда я знаю, что мне понадобится React.useCallback вместо обычного обратного вызова?

2. Лучший совет, который я могу дать, — это посоветовать вам выкроить немного времени для прочтения этой статьи. overreacted.io/a-complete-guide-to-useeffect Это довольно информативно о том, как state работает иначе, чем вы могли бы подумать в React. Понимание концепций, изложенных в статье, поможет вам быстрее распознать этот тип ошибок в будущем.