反应:使用 useReducer 和功能组件将 api 结果变成 table
react: getting api results into a table using useReducer and functional component
我是全新的反应。我正式不再用头撞墙了。我就是想不通。这是我的情况:
我正在尝试获取 API 调用 table 的结果。我接到 API 工作电话,结果回来了。我坚持如何使用返回的数据更新我的数组。完成后,我可以用数据填充 table(至少逻辑上我的大脑是这样告诉我的)。
初始表单状态设置:
const initialFormState = {
fileTypeId : '',
companyMasterId: '',
investmentCompanyId: '',
startDate: '',
endDate: '',
result: '',
fileLogs: []
}
以上所有字段都是form\database上的字段。 API 调用采用这些参数来调用存储过程,该存储过程 returns 基于搜索参数的结果集。 fileLogs[] 是我要放置返回数据的地方。我不确定是否需要将其移出此设置并单独使用 useState?
减速器初始化:
const [formState, dispatch] = useReducer (formReducer, initialFormState)
减速器设置
formReducer.js
import actionTypes from "./actionTypes"
const formReducer = (state, action) => {
switch (action.type) {
case actionTypes.handle_input_text:
return {
//using the spread operator (…state) to copy across all the properties and values from the state object.
//then we can modify the values of specific state properties by explicitly declaring them again with a new value.
...state,
[action.field]: action.payload,
}
case actionTypes.toggle_consent:
return{
...state,
hasConsented: !state.hasConsented
}
case actionTypes.on_success:
return{...state, filelogs: action.payload}
default:
return state
}
}
export default formReducer
API来电
function getFileRouteLogs (e) {
e.preventDefault()
apiService.getFileRouteLogs(
formState.fileTypeId,
formState.companyMasterId,
formState.investmentCompanyId,
formState.startDate,
formState.endDate,
formState.result
)
.then((response)=>{
// dispatch({
// type: actionTypes.on_success,
// // payload: [...formState.fileLogs, response.data]
// payload: response.data
// })
formState.fileLogs = response.data
console.log(response.data)
})
表单输入更改的处理程序
const handleInputChange = (e) => {
dispatch({
type: actionTypes.handle_input_text,
field: e.target.name,
payload: e.target.value
})
}
输入表格
return (
<div>
<h1>File Route Log Search</h1>
<hr />
<h2>Form field area</h2>
<Form onSubmit={getFileRouteLogs}>
<FormGroup row>
<Label for="fileTypeId" sm={2}>FileTypeId</Label>
<Col sm={2}>
<Input type="text" name="fileTypeId" value={formState.fileTypeId} onChange={(e) => handleInputChange(e)}></Input>
</Col>
</FormGroup>
<FormGroup row>
<Label for="companyMasterId" sm={2}>CompanyMasterId</Label>
<Col sm={2}>
<Input id="companyMasterId" type="text" name="companyMasterId" value={formState.companyMasterId} onChange={(e) => handleInputChange(e)} ></Input>
</Col>
</FormGroup>
...
已尝试table设置以保存数据
const FileRouteLogTable = ({formState}) => {
return (
<table className="table">
<thead>
<tr>
<th>FileRouteLogId</th>
<th>CompanyMasterId</th>
<th>FileTypeId</th>
<th>Result</th>
<th>InvestmentCompanyMasterId</th>
<th>FileName</th>
</tr>
</thead>
<tbody>
{ (formState.length > 0) ? formState.map( (form, index) => {
return (
<tr key={ index }>
<td>{ form.fileRouteLogId }</td>
<td>{ form.companyMasterId }</td>
<td>{ form.fileTypeId}</td>
<td>{ form.result }</td>
<td>{ form.investmentCompanyMasterId }</td>
<td>{ form.fileName }</td>
</tr>
)
}) : <tr><td colSpan="5">Enter search parameters...</td></tr> }
</tbody>
</table>
);
}
export default FileRouteLogTable
我本来打算尝试使用 react-table,但在我可以做任何 table 事情之前我被困在更新数据上
import { useTable } from 'react-table'
function FileRouteLogTable({ columns, formState }) {
// Use the state and functions returned from useTable to build your UI
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
} = useTable({
columns,
formState,
})
return (
<table {...getTableProps()}>
<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, i) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
)
})}
</tbody>
</table>
)
}
export default FileRouteLogTable
如有任何帮助,我们将不胜感激。我看的所有例子都没有我的因素组合:
- 功能组件
- 使用useReducer
- 使用 axios
- 不在一页上的所有内容
- 不使用 useEffect
在页面加载时执行 API GET 调用
- 不只是在控制台日志中显示结果
更新
我修复了@johannchopin 提到的大小写问题并更改了负载。 table 中仍然没有任何数据,所以我将 table 逻辑从:
更改为
{ (formState.length > 0) ? formState.map( (form, index) => {
至
{ (formState.fileLogs.length > 0) ? formState.fileLogs.map( (form, index) => {
数据在table
您需要做的第一件事是在 api 调用中更改 then 中的调度。
dispatch({
type: actionTypes.on_success,
payload: [...formState.fileLogs, ...response.data]
})
我上面所做的是因为我认为你的 api 正在返回一个数组。如果不是这样,那么调度就可以了。但是现在您无法将日志直接分配给状态的方式。如果您的回复包含所有数据,那么您可以像下面这样发送
dispatch({
type: actionTypes.on_success,
payload: [...response.data]
})
正如用户@johannchopin在评论中所述,问题是由减速器中的错字引起的。它是“filelogs”,应该是“fileLogs”。我已经更正了。
将您的 formReducer.js 更改为:
const formReducer = (state, action) => {
switch (action.type) {
case actionTypes.handle_input_text:
return {...state, [action.field]: action.payload}
case actionTypes.toggle_consent:
return {...state, hasConsented: !state.hasConsented}
case actionTypes.on_success:
return {...state, fileLogs: action.payload}
default:
return state
}
}
很遗憾,这似乎是 fileLogs
的一个简单的错字问题。在 formReducer
函数中,您将 action.payload
分配给 filelogs
而不是 fileLogs
。进行此更新后,您可以再次使用 dispatch
函数:
.then((response) => {
dispatch({
type: actionTypes.on_success,
payload: response.data
});
});
检查现场示例:
我是全新的反应。我正式不再用头撞墙了。我就是想不通。这是我的情况:
我正在尝试获取 API 调用 table 的结果。我接到 API 工作电话,结果回来了。我坚持如何使用返回的数据更新我的数组。完成后,我可以用数据填充 table(至少逻辑上我的大脑是这样告诉我的)。
初始表单状态设置:
const initialFormState = {
fileTypeId : '',
companyMasterId: '',
investmentCompanyId: '',
startDate: '',
endDate: '',
result: '',
fileLogs: []
}
以上所有字段都是form\database上的字段。 API 调用采用这些参数来调用存储过程,该存储过程 returns 基于搜索参数的结果集。 fileLogs[] 是我要放置返回数据的地方。我不确定是否需要将其移出此设置并单独使用 useState?
减速器初始化:
const [formState, dispatch] = useReducer (formReducer, initialFormState)
减速器设置
formReducer.js
import actionTypes from "./actionTypes"
const formReducer = (state, action) => {
switch (action.type) {
case actionTypes.handle_input_text:
return {
//using the spread operator (…state) to copy across all the properties and values from the state object.
//then we can modify the values of specific state properties by explicitly declaring them again with a new value.
...state,
[action.field]: action.payload,
}
case actionTypes.toggle_consent:
return{
...state,
hasConsented: !state.hasConsented
}
case actionTypes.on_success:
return{...state, filelogs: action.payload}
default:
return state
}
}
export default formReducer
API来电
function getFileRouteLogs (e) {
e.preventDefault()
apiService.getFileRouteLogs(
formState.fileTypeId,
formState.companyMasterId,
formState.investmentCompanyId,
formState.startDate,
formState.endDate,
formState.result
)
.then((response)=>{
// dispatch({
// type: actionTypes.on_success,
// // payload: [...formState.fileLogs, response.data]
// payload: response.data
// })
formState.fileLogs = response.data
console.log(response.data)
})
表单输入更改的处理程序
const handleInputChange = (e) => {
dispatch({
type: actionTypes.handle_input_text,
field: e.target.name,
payload: e.target.value
})
}
输入表格
return (
<div>
<h1>File Route Log Search</h1>
<hr />
<h2>Form field area</h2>
<Form onSubmit={getFileRouteLogs}>
<FormGroup row>
<Label for="fileTypeId" sm={2}>FileTypeId</Label>
<Col sm={2}>
<Input type="text" name="fileTypeId" value={formState.fileTypeId} onChange={(e) => handleInputChange(e)}></Input>
</Col>
</FormGroup>
<FormGroup row>
<Label for="companyMasterId" sm={2}>CompanyMasterId</Label>
<Col sm={2}>
<Input id="companyMasterId" type="text" name="companyMasterId" value={formState.companyMasterId} onChange={(e) => handleInputChange(e)} ></Input>
</Col>
</FormGroup>
...
已尝试table设置以保存数据
const FileRouteLogTable = ({formState}) => {
return (
<table className="table">
<thead>
<tr>
<th>FileRouteLogId</th>
<th>CompanyMasterId</th>
<th>FileTypeId</th>
<th>Result</th>
<th>InvestmentCompanyMasterId</th>
<th>FileName</th>
</tr>
</thead>
<tbody>
{ (formState.length > 0) ? formState.map( (form, index) => {
return (
<tr key={ index }>
<td>{ form.fileRouteLogId }</td>
<td>{ form.companyMasterId }</td>
<td>{ form.fileTypeId}</td>
<td>{ form.result }</td>
<td>{ form.investmentCompanyMasterId }</td>
<td>{ form.fileName }</td>
</tr>
)
}) : <tr><td colSpan="5">Enter search parameters...</td></tr> }
</tbody>
</table>
);
}
export default FileRouteLogTable
我本来打算尝试使用 react-table,但在我可以做任何 table 事情之前我被困在更新数据上
import { useTable } from 'react-table'
function FileRouteLogTable({ columns, formState }) {
// Use the state and functions returned from useTable to build your UI
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
} = useTable({
columns,
formState,
})
return (
<table {...getTableProps()}>
<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, i) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
)
})}
</tbody>
</table>
)
}
export default FileRouteLogTable
如有任何帮助,我们将不胜感激。我看的所有例子都没有我的因素组合:
- 功能组件
- 使用useReducer
- 使用 axios
- 不在一页上的所有内容
- 不使用 useEffect 在页面加载时执行 API GET 调用
- 不只是在控制台日志中显示结果
更新 我修复了@johannchopin 提到的大小写问题并更改了负载。 table 中仍然没有任何数据,所以我将 table 逻辑从:
更改为 { (formState.length > 0) ? formState.map( (form, index) => {
至
{ (formState.fileLogs.length > 0) ? formState.fileLogs.map( (form, index) => {
数据在table
您需要做的第一件事是在 api 调用中更改 then 中的调度。
dispatch({
type: actionTypes.on_success,
payload: [...formState.fileLogs, ...response.data]
})
我上面所做的是因为我认为你的 api 正在返回一个数组。如果不是这样,那么调度就可以了。但是现在您无法将日志直接分配给状态的方式。如果您的回复包含所有数据,那么您可以像下面这样发送
dispatch({
type: actionTypes.on_success,
payload: [...response.data]
})
正如用户@johannchopin在评论中所述,问题是由减速器中的错字引起的。它是“filelogs”,应该是“fileLogs”。我已经更正了。
将您的 formReducer.js 更改为:
const formReducer = (state, action) => {
switch (action.type) {
case actionTypes.handle_input_text:
return {...state, [action.field]: action.payload}
case actionTypes.toggle_consent:
return {...state, hasConsented: !state.hasConsented}
case actionTypes.on_success:
return {...state, fileLogs: action.payload}
default:
return state
}
}
很遗憾,这似乎是 fileLogs
的一个简单的错字问题。在 formReducer
函数中,您将 action.payload
分配给 filelogs
而不是 fileLogs
。进行此更新后,您可以再次使用 dispatch
函数:
.then((response) => {
dispatch({
type: actionTypes.on_success,
payload: response.data
});
});
检查现场示例: