useState не отображает результаты вызова axios, используя async / await с React Hooks - PullRequest
0 голосов
/ 04 октября 2019

Я новичок в React Hooks и не могу исправить проблему с состоянием. Я читал в другом месте по переполнению стека об асинхронной природе useState / useEffect, и кажется, что что бы я ни пытался, в том числе async / await, я не могу присвоить результаты массива JSON моему [data, callback] для визуализации элементов возвращаемых данныхв простой таблице в моем основном приложении (.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 };

таблиц / 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, и представление нового состояния? В частности, «Просмотреть сделку» немного ниже App.js

, заранее благодарен за любые указания!

1 Ответ

1 голос
/ 04 октября 2019

Из useState документации:

Аргумент initialState - это состояние, используемое во время начального рендеринга. При последующих рендерингах это игнорируется.

Во время начального рендеринга App, tradeData - пустой массив, так как выборка еще не завершена. tradeData используется только в качестве аргумента initialState для useState.

Впоследствии, когда выборка завершена и tradeData содержит выбранные данные, это обновленное значение tradeData не копируется в состояние tradesпеременная.

Вы можете использовать эффект для копирования загруженных tradeData в trades:

useEffect(() => {
    setTrades(tradeData)
}, [tradeData]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...