在两个 axios api get 请求之后设置状态之前反应渲染

时间:2021-03-30 16:34:19

标签: reactjs axios use-effect use-state

我正在尝试通过 axios 进行两次调用,等待这些响应,使用 useState 设置相应的变量,将 isLoading 设置为 false,然后呈现我的 React 应用程序。在应用程序尝试呈现之前,我无法加载 fleets。应用程序在 fleets 仍为 null 时尝试呈现,从而导致 TypeError: Cannot read property 'map' of null。解决此问题的最佳方法是什么?为什么我的 .then 链不起作用?

import './App.css';
import React, { useState, useEffect } from 'react';
import axios from 'axios';

function App() {

  const DEFAULT_FLEET = "My Fleet"
  const [selectedFleet, setSelectedFleet] = useState(DEFAULT_FLEET);
  const [contracts, setContracts] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);
  const [fleets, setFleets] = useState(null);

  useEffect(() => {
    Promise.all([
      axios.get('/fleets'),
      axios.get('/contracts?fleet_name=' + selectedFleet)
    ])
    .then(([fleetsResponse, contractsReponse]) => {
      setFleets(fleetsResponse.data);
      setContracts(contractsReponse.data);
    })
    .catch(error => {
      console.log(error);
      setError(error.message)
    })
    .then(console.log(fleets))
    .then(setIsLoading(false))
    
  }, [])

  if (error) {
    return (<>Error: { error }</>)
  } else if (isLoading) {
    return (<div>Is Loading...</div>)
  } else {

    const fleetOptions = fleets.map((fleet) => {
      <option value={fleet.name}> {fleet.name} </option>
    });

  return (
    <div className="App">
      <select>
        {fleetOptions}
        </select>
      <div>{ contracts }</div>
    </div>
  );
  }
}

export default App;

1 个答案:

答案 0 :(得分:1)

大功告成,then 的参数应该是一个函数,当 Promise 实现时将调用该函数。在您的代码中,setIsLoading(false) 在 Promise 仍在获取时执行。尝试更改:

-    .then(setIsLoading(false))
+    .then(() => setIsLoading(false))