如何在另一个 .js 中的数据更改时在 .js 中重新呈现 react-table

How to re-render react-table in .js when data changes in another .js

我是 react-table 的新手,并试图在提供给它的 data 发生变化时重新渲染 react-table。反正有这样做吗?我试过使用 useEffect() 但没有用。

澄清Usage.jsUpdater.js 需要与其功能分开,如图所示。我愿意使用全局变量之外的另一种方法,如果它可以帮助在数据值更改时重新呈现 table。

table.js

import React, {useMemo} from 'react'
import {useTable} from 'react-table'

export const Table = ({ columns, data, noDataComponent, ...rest }) => {
  const tableColumns = useMemo(() => columns, [columns]);
  const { getTableBodyProps, getTableProps, headerGroups, prepareRow, rows } = useTable({ columns: tableColumns, data });

  if (!rows.length) {
    if (noDataComponent) return noDataComponent;
    return <>No data</>;
  }

React.useEffect(() => {}, [data]) //does not re-render table

  return (
    <table {...getTableProps()} {...rest}>
      <thead>
        {headerGroups.map((headerGroup) => (
          <tr {...headerGroup.getHeaderGroupProps()}>
            {headerGroup.headers.map((column) => (
              <th {...column.getHeaderProps()}>{column.render('Header')}</th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody {...getTableBodyProps()}>
        {rows.map((row) => {
          prepareRow(row);
          return (
            <tr {...row.getRowProps()}>
              {row.cells.map((cell) => {
                const { className, style } = cell.column;
                return (
                  <td {...cell.getCellProps({ className, style })}>
                    {cell.render('Cell')}
                  </td>
                );
              })}
            </tr>
          );
        })}
      </tbody>
    </table>
  );
};

globalVariable.js

module.exports = global.config = {
value: { exactval: [] }
}

Usage.js

data 通过在 Updater.js 中使用 GET 请求更新并在 globalVariable.js[ 中使用全局变量提供=68=].

import {Table} from './table.js'
...

<Table data={global.config.value.exactval} columns={COLS} />

Updater.js

import './globalVariable.js'

...

function DummyCall() { //Works fine 
    axios.get(URL, headers)
    .then(reponse => {
        global.config.value.exactval.push(reponse.ID[1])
        }
    ).catch(error => {
        console.log(error)
    }) }

...

<button type ="button" onClick={() => DummyCall()} > Test me! </button>

将不胜感激带有示例代码的简单解释。

编辑 #1:添加了数据更新方式

编辑#2: 在听取@Obsidianlab 和@Johnny 的建议后,我使用 Context API 和 Johnny 的回答(回答中有一个重要的错误需要将 .Provider 包装在 return() 中,我得到以下奇怪的行为:

Updater.js

根据@Johnny 的步骤更新

import './globalVariable.js'

...

function DummyCall() { //Works fine 
    const updatedData = { ...context.data };

    axios.get(URL, headers)
        .then(reponse => {
            global.config.value.exactval.push(reponse.ID[1])
            updatedData.data.push(reponse.ID[1]);

        }
    context.setData(updatedData)
    ).catch(error => {
        console.log(error)
}) }

...

<button type ="button" onClick={() => DummyCall()} > Test me! </button>

对于Usage.js

下面的代码可以工作并重新呈现

const context = useContext(TableDataContext) //needs to be there
<Table data={global.config.value.exactval} columns={COLS} />

下面的代码 不会重新呈现 ,但是控制台显示 context.data.exactval 值已更新。

const context = useContext(TableDataContext);
...
<Table data={context.data.exactval} columns={COLS} />

如何解决与 Context API 相关的非渲染问题?

我猜你不能重新渲染组件,除非你只是向元素提供静态变量。 对于 re-render 的组件,当它们发生变化时,您必须将该值存储到状态并将该状态传递到 useEffect 的依赖数组中。 林克:

const [value,setValue] = useState({})
.....
//and in useEffect

useEffect(() => {}, [value]) 

试试这个,也许会奏效。

因此,根据我的理解,您正在更新在 js 文件中创建的全局变量 ./globalVariable.js。我没有看到该文件,但我相信这些变量超出了 react 可以“关注”的范围。

所以我建议您在 Usage.js 中为您的数据创建一个状态,然后更新它。示例:

Usage.js

import { Table } from './table.js';
...
const [data, setData] = useState(initialData); //define your inital data like your global variables

async function DummyCall() {
  try {
    const response = await axios.get(URL, headers);
    if(response.status === 200) {
       const updatedData = { ...data };
       updatedData.config.value.exactval.push(reponse.ID[1]);
       setData(updatedData)
    }

  } catch(error) {
    console.log(error);
  }
}
...
<button type ="button" onClick={() => DummyCall()} > Test me! </button>

编辑#1

由于您不能合并两个文件或导出函数,我建议您使用 ContextAPI

TableDataContext.js

import { createContext } from 'react'

const TableDataContext = createContext();

const TableDataProvider = ({ children }) => {
  const [data, setData] = useState(initialData); //define your inital 

  <TableDataContext.Provider value={{ data, setData }}>
    {children}
  </TableDataContext.Provider>
}

export { TableDataContext, TableDataProvider };

现在您必须包装您需要使用提供程序TableDataContext的组件

如果你想在你的整个应用程序中,例如:

import { TableDataProvider } from 'path/to/context/TableDataContext'

<TableDataProvider>
  <App/>
</TableDataProvider>

这样,您可以通过从上下文中导入 setDataDummyCall 中:

Updater.js

import { useContext } from 'react';
import { TableDataContext } from 'path/to/context/TableDataContext'
....
const context = useContext(TableDataContext);

async function DummyCall() { 
   //...code
   // on setData
   const updatedData = { ...context.data };
   updatedData.config.value.exactval.push(reponse.ID[1]);
   context.setData(updatedData)
}

最后只需从您的 table.js 中的上下文中导入数据,您将不需要通过 props

您可以在 React Docs

上了解有关 ContextAPI 的更多信息

希望有用