【问题标题】:react: getting api results into a table using useReducer and functional componentreact: 使用 useReducer 和功能组件将 api 结果放入表中
【发布时间】:2021-08-13 20:43:05
【问题描述】:

我是全新的反应。我正式完成了用头撞墙。我就是想不通。这是我的情况:

我正在尝试将 API 调用的结果放入表中。我有调用 API 的工作,结果回来了。我被困在如何用返回的数据更新我的数组。完成之后,我可以用数据填充表格(至少在逻辑上这是我的大脑告诉我的方式)。

初始表单状态设置:

const initialFormState = {
    fileTypeId : '',
    companyMasterId: '',
    investmentCompanyId: '',
    startDate: '',
    endDate: '',
    result: '',
    fileLogs: []
}

以上所有字段都是表单\数据库中的字段。 API 调用采用这些参数来调用存储过程,该存储过程根据搜索参数返回结果集。 fileLogs[] 是我想要放置返回数据的地方。我不确定是否需要将其移出此设置并仅将 useState 用作单独的东西?

reducer 初始化:

 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> 
...

已尝试设置表以保存数据

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,但在我可以做任何表格内容之前,我一直在更新数据

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 提到的套管问题并更改了有效负载。我的表中仍然没有任何数据,所以我将表逻辑从:

 { (formState.length > 0) ? formState.map( (form, index) => {

到

 { (formState.fileLogs.length > 0) ? formState.fileLogs.map( (form, index) => {

数据在表格中

【问题讨论】:

    标签: reactjs react-hooks use-reducer


    【解决方案1】:

    很遗憾,fileLogs 似乎是一个简单的拼写错误问题。在formReducer 函数中,您将action.payload 分配给filelogs 而不是fileLogs。进行此更新后,您可以再次使用dispatch 函数:

        .then((response) => {
          dispatch({
            type: actionTypes.on_success,
            payload: response.data
          });
        });
    

    查看实时示例:

    【讨论】:

    • 最初我在 api 服务中返回 response.data。我将其更改为仅返回响应,然后像您一样更改了有效负载。在对检查数组的长度属性的方式进行了一些小改动之后,我的表中现在有了数据。谢谢
    • @MikeV Ahah 没问题。在那之后,我会鼓励你在你的项目中设置 TypeScript 来真正解决所有这些小错误 :) 学习它确实需要时间。
    • @MikeV 你能不能也给我的答案投票,这样我就可以得到赏金,以防 user2315985 忘记手动奖励它:)
    【解决方案2】:

    您需要做的第一件事是在 api 调用中的 then 中更改调度。

    dispatch({
        type: actionTypes.on_success,
        payload: [...formState.fileLogs,  ...response.data]
    })
    
    

    我上面所做的是因为我认为您的 api 正在返回一个数组。如果不是这样,那么调度是好的。但是现在您将日志直接分配给状态的方式,您不能这样做。如果您的回复包含所有数据,那么您可以像下面这样发送

    dispatch({
        type: actionTypes.on_success,
        payload: [...response.data]
    })
    
    

    【讨论】:

    • 在response.data 上使用扩展运算符没有任何优势。使用payload: response.data 完全有效。
    • 虽然这确实有效,但只有在我纠正了@johannchopin 下面提到的大小写问题之后
    【解决方案3】:

    正如用户 @johannchopin 在 cmets 中所说,问题是由减速器中的拼写错误引起的。它是“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
      }
    }
    

    【讨论】:

    • 你为什么要这样做,初始实现是正确的,在这种情况下请不要做一个反应状态的JSON.parse(JSON.stringify(...)):/看我的回答问题来自filelogs的错字那应该是fileLogs。
    • 我明白了,问题出在拼写错误上。我会更新我的答案。而且,你也可以使用我的 reducer 实现,这看起来更简洁易读:)
    • 对不起,但不得不否决您的答案。使用JSON.parse(JSON.stringify(state)) 在No Way“更干净”。在每次状态更新时,您完全没有理由执行 2 次代价高昂的操作(在这种情况下不需要克隆状态)。请遵循在state 上直接使用扩展运算符的原始实现。
    • @johannchopin 我已经编辑了我的答案。但是你能解释一下为什么JSON.parse(JSON.stringify(state)) 是一项昂贵的操作吗?
    • @johannchopin 经过我自己的研究,我发现JSON.parse(JSON.stringify(state)) 和直接使用扩展运算符,提供相同级别的性能!如果您关心性能,请查看强大的工具,例如 lodash。他们好多了。
    猜你喜欢
    • 2022-07-08
    • 2023-02-08
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 2020-12-22
    • 2020-08-12
    相关资源
    最近更新 更多