TanStack / table

🤖 Headless UI for building powerful tables & datagrids for TS/JS - React-Table, Vue-Table, Solid-Table, Svelte-Table
https://tanstack.com/table
MIT License
25.1k stars 3.07k forks source link

State does not update after inspecting data in dev tools #4293

Open caboddie1 opened 2 years ago

caboddie1 commented 2 years ago

Describe the bug

This could potentially be an issue with React Dev tools however, I am unable to replicate it with any other react code.

After opening React Dev Tools and inspecting props/data I am unable to change pages or toggle sorting on any of my table components. It seems to freeze the component.

image

Your minimal, reproducible example

https://codesandbox.io/s/github/tanstack/table/tree/main/examples/react/pagination?from-embed

Steps to reproduce

I was unable to replicate within code sandbox as the code you write is created within an iframe if I'm not mistaken?

  1. Copy the pagination example into a new typescript react project with create react app.
  2. Navigate between pages using the arrows.
  3. Open the React dev tools and inspect the component.
  4. Try to navigate between pages again - it usually freezes at this point.

Have tried in Chrome, Edge and Firefox.

Expected behavior

I expect to be able to inspect data/props in the dev tools to see how it changes with different interactions.

How often does this bug happen?

Every time

Screenshots or Videos

No response

Platform

screen-capture (1).webm

react-table version

8.5.2

TypeScript version

4.4.3

Additional context

No response

Terms & Code of Conduct

CaptainObi commented 2 years ago

I've also had this issue. For me it seems to freeze whenever I try to use a useState hook or one of my zustand actions on a row click.

kasparsuvi1 commented 2 years ago

It's really annoying problem. And it is quite difficult to get to the root of the problem. Because all of the other code is running and working, only react state dispatches are not run.

So if u have something like that with react devtools open

  const rowSelectionChange = (data: Updater<RowSelectionState>): void => {
    if (typeof data === 'function') {
      console.log(rowSelection) // console.logs default rowSelection
      const newRowSelection = data(rowSelection);
      console.log(newRowSelection) // console.logs calculated rowSelection
      setRowSelection(newRowSelection); // Does not update the state
      console.log(newRowSelection) // console.logs calculated rowSelection
      // setRowSelection({ 1: true, 2: true }); // if uncommented will be called and set to state!
    }
  };

Same problem occurs with (onSortingChange, onPaginationChange, onExpandedChange). Hoping that it helps someone to google the problem...

martavis commented 1 year ago

Hi all. I spent many hours trying to figure out why my table wasn't sorting or paginating, and closing the dev tools worked. My example was attempting to do basic sorting like this:

const [sorting, setSorting] = useState<SortingState>([{ id: "username", desc: false }]);

const usersTable = useReactTable({
  data,
  columns,
  state: { sorting },
  onSortingChange: setSorting,
  getCoreRowModel: getCoreRowModel(),
  getSortedRowModel: getSortedRowModel(),
});

And the table didn't sort while the React Devtools extension was enabled. Does anyone know why this is an issue or how to fix it? So far, I see a possible connection in React's issues: https://github.com/facebook/react/issues/16891

kboul commented 1 year ago

same problem here. state freezes when using react dev tools

ppaul commented 7 months ago

same issue; I have a plugin that puts a checkAll checkbox in header and need to verify and extend some behavior.

elijaholmos commented 4 months ago

same issue, react devtools broke the table onSortingChange / setSorting methods.... very annoying to debug

SigmaInfini commented 4 months ago

I encountered the same issue. It seems that React Developer Tools call the component solely for inspection purposes. I assumed that the setState function provided last can invoke re-rendering, but it is not with that tools.

Below is the proof code

https://github.com/TanStack/table/assets/56242170/df101741-e7fe-4006-ab03-3cbbb25f6ab2

import { useEffect } from "react";
import { useState } from "react"

export const InternalCallbackButton = (params) => {
    const [state,setState] = useState(0);

    const myClick  = () => {
        setState(state+1);
    }

    return (
        <button onClick={myClick}>InternalCallback: {state}</button>
    );
}

type setStateFunction = (state:number) => void; 

const StoreA : {
    Last1? : setStateFunction;
} = {};

export const ExranalCallbackWith_Last1_SetStateButton = (params) => {
    const [state,setState] = useState(0);
    StoreA.Last1 = (a) => setState(a);

    const myClick  = () => {
        if (StoreA.Last1!==undefined)
            StoreA.Last1(state+1);
    };

    return (
        <button onClick={myClick}>ExternalCallback with Last 1 SetState(): {state}</button>
    );
};

const StoreB : {
    Last1? : setStateFunction;
    Last2? : setStateFunction;
} = {};

export const ExranalCallbackWith_Last2_SetStateButton = (params) => {
    const [state,setState] = useState(0);
    StoreB.Last2 = StoreB.Last1;
    StoreB.Last1 = (a) => setState(a);

    const myClick  = () => {
        if (StoreB.Last1!==undefined)
            StoreB.Last1(state+1);
        if (StoreB.Last2!==undefined)
            StoreB.Last2(state+1);
    };

    return (
        <button onClick={myClick}>ExternalCallback with Last 1&2 SetState(): {state}</button>
    );
};

const StoreC : {
    Last1? : setStateFunction
} = {};

export const ExranalCallbackWith_UseEffect_Last1_SetStateButton = (params) => {
    const [state,setState] = useState(0);

    useEffect(()=>
    {
        StoreC.Last1 = (a) => setState(a);
        return () => {
            StoreC.Last1 = undefined;
        }
    },[]);

    const myClick  = () => {
        if (StoreC.Last1!==undefined)
            StoreC.Last1(state+1);
    }

    return (
        <button onClick={myClick}>ExternalCallback with UseEffectd Last1SetStateFunction: {state}</button>
    );
}

With React Developer Tools component inspection:

(1) There are no issues with InternalCallback.

(2) ExranalCallbackWith_Last1_SetStateButton does not work when selected in the tool. This is because the latest setState function is overridden by a dummy function from the tool.

(3) ExranalCallbackWith_Last2_SetStateButton works. The latest setState function is overridden by a dummy function from the tool, but the previous setState function remains and can invoke re-rendering.

(4) There are no issues with ExranalCallbackWith_UseEffect_Last1_SetStateButton. This seems to be the answer I was looking for.

That's all.

To simplify the problem, I used a global callback. In reality, I encountered this issue with callbacks from external data objects. Because I was using closures, the setState function was unintentionally captured and then overridden by a dummy function from React Developer Tools, causing it to stop working.

I hope my experience can be of some help to you all.