【问题标题】:useState doesn't render results of axios call using async/await with React HooksuseState 不使用带有 React Hooks 的 async/await 渲染 axios 调用的结果
【发布时间】:2020-02-02 06:23:01
【问题描述】:

我是 React Hooks 的新手,无法解决状态问题。我在 Stack Overflow 上的其他地方读过关于 useState/useEffect 的异步性质的文章,似乎无论我尝试什么,包括 async/await,我都无法将 JSON 数组结果分配给我的 [data, callback] 以呈现返回数据的元素在我的主 App(.js) 中的一个简单表格中 - 见下文。我有一个App.js、一个Hooks.js 和一个Tradetable.js,其中填充了元素表(后两个文件导入到App.js 中)。

App.js

import React, { useState, Fragment } from 'react'
import AddTradeForm from './forms/AddTradeForm'
import EditTradeForm from './forms/EditTradeForm'
import TradeTable from './tables/TradeTable'
import { useFetch } from './Hooks'

const App = () => {
    // get Data from API call
    const URL = "http://192.168.1.1:3000/api/queryMyCommodity"; //
    const tradeData = useFetch(URL, {username:'john', channel:'channel1', name: 'GOLD'}); // the result of this `axios` call inside `useFetch` (in Hooks.js below), is exactly the same as the commented `const` line below - which would work just fine for table item rendering, ie when testing with a JSON array of 3 table items.

// const tradeData = [{"class":"demoCommodity","description":"really fabulous gold","fcn":"demoCreate","id":"trade001","name":"GOLD","owner":"JOHAN.BRINKS","tradename":"GLD"},{"class":"org.example.trading.Commodity","description":"more fabulous gold","fcn":"demoCreate","id":"trade004","name":"GOLD","owner":"NED.SLIVOVITZ","tradename":"GLD"},{"class":"org.example.trading.Commodity","description":"absolutely fabulous gold","fcn":"demoCreate","id":"trade005","name":"GOLD","owner":"ED.GOLDBERG","tradename":"GLD"}]

    // Setting state
    const [trades, setTrades ] = useState(tradeData); // this is the line with the issue
    console.log("trades in App is set to " + JSON.stringify(trades)); // `trades` is empty [] but `tradeData` has data, being evaluated later perhaps?
    const initialFormState = { id: '' , name: '', tradename: '' }; // not using all fields in form fyi
    const [ currentTrade, setCurrentTrade ] = useState(initialFormState)
    const [ editing, setEditing ] = useState(false)

    // CRUD operations
    const addTrade = trade => {
        trade.id = trades.length + 1
        setTrades([ ...trades, trade ])
    }

    const deleteTrade = id => {
        setEditing(false)

        setTrades(trades.filter(trade => trade.id !== id))
    }

    const updateTrade = (id, updatedTrade) => {
        setEditing(false)

        setTrades(trades.map(trade => (trade.id === id ? updatedTrade : trade)))
    }

    const editRow = trade => {
        setEditing(true)

        setCurrentTrade({ id: trade.id, name: trade.name, tradename: trade.tradename })
    }

    return (
        <div className="container">
            <h1>Trading App CRUD-style</h1>
            <div className="flex-row">
                <div className="flex-large">
                    {editing ? (
                        <Fragment>
                            <h2>Edit trade</h2>
                            <EditTradeForm
                                editing={editing}
                                setEditing={setEditing}
                                currentTrade={currentTrade}
                                updateTrade={updateTrade}
                            />
                        </Fragment>
                    ) : (
                        <Fragment>
                            <h2>Add trade</h2>
                            <AddTradeForm addTrade={addTrade} />
                        </Fragment>
                    )}
                </div>
                <div className="flex-large">
                    <h2>View trades</h2>
                    <TradeTable trades={trades} editRow={editRow} deleteTrade={deleteTrade} />
                </div>
            </div>
        </div>
    )
}

export default App

Hooks.js

import React, { useState, useEffect } from "react";
import axios from 'axios'

const useFetch = (httpurl, options) => {
const [mydata, setData] = useState([]);

  useEffect(() => {
    async function fetchData() {
       const response = await axios({
              method: 'POST',
              url : httpurl,
              headers: {
              'Accept': 'application/json',
              'Content-Type': 'application/json'
              },
              data: options
      });
      setData(response.data);  // what comes back is set to a JS variable called 'data'
    }
    fetchData();
  }, [httpurl]);

   return mydata;
};

export { useFetch };

tables/TradeTable.js

import React from 'react'

// this is where the App will process `trades` and process/render to view in a table, then take a CRUD action etc.

const TradeTable = props => (
  <table>
    <thead>
      <tr>
        <th>Name</th>
        <th>Tradename</th>
        <th>Trade Actions</th>
      </tr>
    </thead>
    <tbody>
      {props.trades.length > 0 ? (
        props.trades.map(trade => (
          <tr key={trade.id}>
            <td>{trade.name}</td>
            <td>{trade.tradename}</td>
            <td>
              <button
                onClick={() => {
                  props.editRow(trade)
                }}
                className="button muted-button"
              >
                Edit
              </button>
              <button
                onClick={() => props.deleteTrade(trade.id)}
                className="button muted-button"
              >
                Delete
              </button>
            </td>
          </tr>
        ))
      ) : (
        <tr>
          <td colSpan={3}>No trades</td>
        </tr>
      )}

那么 - 如何确保 trades[] 由来自 axios 调用的数据填充并代表新的 State ?特别是,“查看交易”位进一步下降App.js

非常感谢任何指导!

【问题讨论】:

  • 您能否添加代码,说明您如何将tradeData 传递给TradeTable?在您共享的代码中,没有提及您如何使用TradeTable
  • App.js 中添加了更多部分 - 查看&lt;h2&gt;View trades&lt;/h2&gt; 部分。

标签: javascript reactjs react-hooks


【解决方案1】:

来自useState 文档:

initialState 参数是初始渲染期间使用的状态。 在随后的渲染中,它被忽略了。

App 的初始渲染期间,tradeData 是一个空数组,因为 fetch 尚未完成。 tradeData 仅用作 useState 的 initialState 参数。

随后,当提取完成并且tradeData 持有提取的数据时,tradeData 的更新值不会复制到trades 状态变量中。

您可以使用效果将加载的tradeData复制到trades

useEffect(() => {
    setTrades(tradeData)
}, [tradeData]);

【讨论】:

    猜你喜欢
    • 2020-11-19
    • 1970-01-01
    • 2021-05-10
    • 2020-06-13
    • 2019-06-26
    • 2021-01-07
    • 1970-01-01
    • 2019-07-01
    • 1970-01-01
    相关资源
    最近更新 更多