TypeError: Cannot read properties of undefined (reading 'forEach') when trying to combine react-table with react-query
TypeError: Cannot read properties of undefined (reading 'forEach') when trying to combine react-table with react-query
我正在尝试将 react-table 与 react-query 结合起来以获得动态的 editable table ,它最初由数据库中的数据填充。
import React from 'react';
import Style from './CLGridStyle.js';
import axios from 'axios';
import { useTable, useBlockLayout, useResizeColumns } from 'react-table';
import { useQuery, QueryClient, QueryClientProvider, useQueryClient } from 'react-query'
const EditableCell = ({
value: initialValue,
row: { index },
column: { id, type, readonly },
updateMyData,
}) => {
// We need to keep and update the state of the cell normally
const [value, setValue] = React.useState(initialValue)
const onChange = e => {
setValue(e.target.value)
}
const onCheckboxChange = e => {
setValue(e.target.checked);
}
// We'll only update the external data when the input is blurred
const onBlur = () => {
updateMyData(type, index, id, value);
}
// If the initialValue is changed external, sync it up with our state
React.useEffect(() => {
setValue(initialValue)
}, [initialValue])
switch (type) {
case 'checkbox':
return (<input onChange={onCheckboxChange} onBlur={onBlur} type={type} readOnly={readonly}
autoComplete="off" checked={value || false} />);
case 'date':
return (<input onChange={onChange} onBlur={onBlur} type={type} readOnly={readonly}
autoComplete="off" value={(value || "").slice(0, 10)} />);
default:
return (<input onChange={onChange} onBlur={onBlur} type={type} readOnly={readonly}
autoComplete="off" value={value || ""} />);
}
}
function CLGrid({ columns }) {
const queryClient = useQueryClient();
const [data, setData] = React.useState([]);
const { apiResponse, isLoading } = useQuery('users', () => axios.get(`http://www.test.devel/users`));
React.useEffect(() => {
setData(apiResponse?.data);
}, [apiResponse]);
const updateMyData = (type, rowIndex, columnId, value) => {
setData(old =>
old.map((row, index) => {
if (index === rowIndex) {
return {
...old[rowIndex],
[columnId]: value,
}
}
return row
})
)
}
const defaultColumn = React.useMemo(
() => ({
minWidth: 30,
width: 150,
maxWidth: 400,
Cell: EditableCell,
}),
[]
);
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
state,
} = useTable(
{
columns, data, defaultColumn, updateMyData
},
useBlockLayout,
useResizeColumns
);
React.useEffect(() => {
if (state.columnResizing.isResizingColumn === null) {
console.log('columnResizing', state.columnResizing);
}
}, [state.columnResizing]);
if (isLoading || !data) {
return (<div>Loading...</div>);
}
return (
<Style>
<div {...getTableProps()} className="table">
<div>
{headerGroups.map(headerGroup => (
<div {...headerGroup.getHeaderGroupProps()} className="tr">
{headerGroup.headers.map(column => (
<div {...column.getHeaderProps()} className="th">
{column.render('Header')}
<div {...column.getResizerProps()} className="resizer" />
</div>
))}
</div>
))}
</div>
<div {...getTableBodyProps()}>
{rows.map((row, i) => {
prepareRow(row)
return (
<div {...row.getRowProps()} className="tr">
{row.cells.map(cell => {
return (
<div {...cell.getCellProps()} className="td">
{cell.render('Cell')}
</div>
)
})}
</div>
)
})}
</div>
</div>
<pre>
<code>{JSON.stringify(state, null, 2)}</code>
</pre>
<pre>
<code>{JSON.stringify(data, null, 2)}</code>
</pre>
</Style>
)
}
const client = new QueryClient();
const ReactQueryWithTable = ({columns}) => {
return (
<QueryClientProvider client={client}>
<CLGrid columns={columns} />
</QueryClientProvider>
);
}
export default ReactQueryWithTable;
当我尝试 运行 这个时,我得到这个错误:
TypeError: Cannot read properties of undefined (reading 'forEach')
发生在 useTable
挂钩中的这个位置:
> 591 | data.forEach((originalRow, rowIndex) =>
592 | accessRow(originalRow, rowIndex, 0, undefined, rows)
593 | )
到目前为止,我已经花了几个小时对此进行调整,但无济于事。我错过了什么?
useQuery
没有名为 apiResponse
的 属性,因此这可能不起作用:
const { apiResponse, isLoading } = useQuery(...)
useQuery
returns 一个名为 data
的字段,您的 api 请求的响应将在其中可用。
我正在尝试将 react-table 与 react-query 结合起来以获得动态的 editable table ,它最初由数据库中的数据填充。
import React from 'react';
import Style from './CLGridStyle.js';
import axios from 'axios';
import { useTable, useBlockLayout, useResizeColumns } from 'react-table';
import { useQuery, QueryClient, QueryClientProvider, useQueryClient } from 'react-query'
const EditableCell = ({
value: initialValue,
row: { index },
column: { id, type, readonly },
updateMyData,
}) => {
// We need to keep and update the state of the cell normally
const [value, setValue] = React.useState(initialValue)
const onChange = e => {
setValue(e.target.value)
}
const onCheckboxChange = e => {
setValue(e.target.checked);
}
// We'll only update the external data when the input is blurred
const onBlur = () => {
updateMyData(type, index, id, value);
}
// If the initialValue is changed external, sync it up with our state
React.useEffect(() => {
setValue(initialValue)
}, [initialValue])
switch (type) {
case 'checkbox':
return (<input onChange={onCheckboxChange} onBlur={onBlur} type={type} readOnly={readonly}
autoComplete="off" checked={value || false} />);
case 'date':
return (<input onChange={onChange} onBlur={onBlur} type={type} readOnly={readonly}
autoComplete="off" value={(value || "").slice(0, 10)} />);
default:
return (<input onChange={onChange} onBlur={onBlur} type={type} readOnly={readonly}
autoComplete="off" value={value || ""} />);
}
}
function CLGrid({ columns }) {
const queryClient = useQueryClient();
const [data, setData] = React.useState([]);
const { apiResponse, isLoading } = useQuery('users', () => axios.get(`http://www.test.devel/users`));
React.useEffect(() => {
setData(apiResponse?.data);
}, [apiResponse]);
const updateMyData = (type, rowIndex, columnId, value) => {
setData(old =>
old.map((row, index) => {
if (index === rowIndex) {
return {
...old[rowIndex],
[columnId]: value,
}
}
return row
})
)
}
const defaultColumn = React.useMemo(
() => ({
minWidth: 30,
width: 150,
maxWidth: 400,
Cell: EditableCell,
}),
[]
);
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
state,
} = useTable(
{
columns, data, defaultColumn, updateMyData
},
useBlockLayout,
useResizeColumns
);
React.useEffect(() => {
if (state.columnResizing.isResizingColumn === null) {
console.log('columnResizing', state.columnResizing);
}
}, [state.columnResizing]);
if (isLoading || !data) {
return (<div>Loading...</div>);
}
return (
<Style>
<div {...getTableProps()} className="table">
<div>
{headerGroups.map(headerGroup => (
<div {...headerGroup.getHeaderGroupProps()} className="tr">
{headerGroup.headers.map(column => (
<div {...column.getHeaderProps()} className="th">
{column.render('Header')}
<div {...column.getResizerProps()} className="resizer" />
</div>
))}
</div>
))}
</div>
<div {...getTableBodyProps()}>
{rows.map((row, i) => {
prepareRow(row)
return (
<div {...row.getRowProps()} className="tr">
{row.cells.map(cell => {
return (
<div {...cell.getCellProps()} className="td">
{cell.render('Cell')}
</div>
)
})}
</div>
)
})}
</div>
</div>
<pre>
<code>{JSON.stringify(state, null, 2)}</code>
</pre>
<pre>
<code>{JSON.stringify(data, null, 2)}</code>
</pre>
</Style>
)
}
const client = new QueryClient();
const ReactQueryWithTable = ({columns}) => {
return (
<QueryClientProvider client={client}>
<CLGrid columns={columns} />
</QueryClientProvider>
);
}
export default ReactQueryWithTable;
当我尝试 运行 这个时,我得到这个错误:
TypeError: Cannot read properties of undefined (reading 'forEach')
发生在 useTable
挂钩中的这个位置:
> 591 | data.forEach((originalRow, rowIndex) =>
592 | accessRow(originalRow, rowIndex, 0, undefined, rows)
593 | )
到目前为止,我已经花了几个小时对此进行调整,但无济于事。我错过了什么?
useQuery
没有名为 apiResponse
的 属性,因此这可能不起作用:
const { apiResponse, isLoading } = useQuery(...)
useQuery
returns 一个名为 data
的字段,您的 api 请求的响应将在其中可用。