3

I am rebuilding a react-table to v8 where one cell is a functional component, which shows the status, based on the Id value.

My Status component is defined like this:

function Status({ id }) {
  const [status, setStatus] = useState("pending");
  useEffect(() => {
    getApi(`/status/${id}`).then((stat) => {
      setStatus(stat);
    });
  }, []);
  return status == "pending" ? (
    <p>Pending</p>
  ) : (
    <p>{status}</p>
  );
}

The column is defined like this:

columnHelper.accessor("id", {
      header: () => "Latest Status",
      cell: (info) =>  <Status id={info.getValue()} />

For rendering the cell I am using FlexRender

flexRender(cell.column.columnDef.cell,cell.getContext())

With this, I get only the "Pending" when the cell renders, the state on the component is not getting updated, even after the API provides the response.

I had the same concept on React-Table v7 using cell.render("Cell") and it works as expected.

Telito
  • 90
  • 1
  • 10

2 Answers2

0

flexRender is creating a new component instead of re-rendering it. I would suggest you wrap it under useMemo so that react keep track of the previously created reference or just try to implement your own logic like if cell.column.columnDef.cell is a react component or not and render it accordingly.

0

I had the same issue and turned out to be my columns and defaultColumn definitions were out of components so they were not reinitialized on data change (Probably keeps the old value in the memory or something like that, i don't know how it works internally)

const columns = [
    columnHelper.accessor('phone', {
      cell: info => (
        <span>
          {info.getValue()}
        </span >
      )
    }),
    columnHelper.accessor('name', {}),
    columnHelper.accessor('email', {})
]

const defaultColumn: Partial<ColumnDef<TypeHere>> = {
    cell: function Cell({ getValue, row: { index }, column, table }) {
      const initialValue = getValue()
      const [value, setValue] = useState(initialValue)

      const onBlur = async () => {
        // ...
      }

      return (
        <input
          value={(value ?? '').toString()}
          onChange={e => setValue(e.target.value)}
          onBlur={onBlur}
        />
      )
    }
}

These above column definitions that are passed to useReactTable were defined on top of my file, which is outside of component function. When i moved them inside the component it worked.

Or instead of all these, just include this piece of code to defaultColumn before return. No need to move your definitions inside component.

useEffect(() => {
   setValue(initialValue)
}, [initialValue])
Doğukan Akkaya
  • 423
  • 3
  • 12