如何在另一个 .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.js
和 Updater.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>
这样,您可以通过从上下文中导入 setData
在 DummyCall
中:
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 的更多信息
希望有用
我是 react-table
的新手,并试图在提供给它的 data
发生变化时重新渲染 react-table
。反正有这样做吗?我试过使用 useEffect() 但没有用。
澄清:Usage.js
和 Updater.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>
这样,您可以通过从上下文中导入 setData
在 DummyCall
中:
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 的更多信息希望有用