我是React Hooks的新手,我无法解决State问题。我已经在Stack Overflow的其他地方阅读了有关useState / useEffect的异步性质的信息,看来无论我尝试什么,包括异步/等待,我都无法将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
非常感谢您提供任何指导!
答案 0 :(得分:1)
摘自useState
文档:
initialState参数是初始渲染期间使用的状态。 在随后的渲染中,将忽略它。
在App
的初始呈现期间,tradeData
是一个空数组,因为尚未完成提取。 tradeData
仅用作useState
的initialState参数。
随后,当获取完成并且tradeData
保留了获取的数据时,tradeData
的更新值不会复制到trades
状态变量中。
您可以使用效果将已加载的tradeData
复制到trades
:
useEffect(() => {
setTrades(tradeData)
}, [tradeData]);