反应:使用 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

如有任何帮助,我们将不胜感激。我看的所有例子都没有我的因素组合:

更新 我修复了@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
      });
    });

检查现场示例: