React - function does not print current states

274 Views Asked by At

Playing with Fluent UI DetailsList, I've created this solution. I've deleted all unnecessary lines to minimize the problem, as it appears that when logging in onColumnClick then somehow it doesn't print the current state but the initial state, why is this happening:

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 && 
    <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>;
      }
    },

    }
  ]
} 

In that

1

There are 1 best solutions below

2
On BEST ANSWER

When you are rendering your component, it creates this function onColumnClick and looks at what the columns are in this very moment. It passes that function into the handlers, remembering what those columns were. (In your case, an empty array.)

In order to update the function when columns update, you need to use useCallback. It is a similar pattern to useEffect, but returns a function instead of runs a function whenever the dependencies change.

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])