Reactjs 如何等待在react中填充数据?

Reactjs 如何等待在react中填充数据?,reactjs,axios,fetch,react-context,use-context,Reactjs,Axios,Fetch,React Context,Use Context,我遇到了一个奇怪的问题,petData最初以未定义的形式记录到控制台,几分钟后填充数据数组。我假设这与获取数据然后通过上下文发送所需的时间有关。问题是应用程序正在崩溃,错误为“TypeError:无法访问属性”name,“petData[0]未定义”我尝试使用setTimeout,但没有帮助。有什么解决办法吗 function SearchPage() { const { petData } = useContext(PetDataContext); console.log(petDat

我遇到了一个奇怪的问题,petData最初以未定义的形式记录到控制台,几分钟后填充数据数组。我假设这与获取数据然后通过上下文发送所需的时间有关。问题是应用程序正在崩溃,错误为“TypeError:无法访问属性”name,“petData[0]未定义”我尝试使用setTimeout,但没有帮助。有什么解决办法吗

function SearchPage() {
  const { petData } = useContext(PetDataContext);
  console.log(petData[0].name);

  const [filter, setFilter] = useState("");

  const filteredData = useMemo(() => {
    if (filter == "") return petData;
    return petData.filter(
      (item) =>
        item.name.toLowerCase().includes(filter) ||
        item.breed.toLowerCase().includes(filter)
    );
  }, [petData, filter]);

  return (
    <>
      <SearchBar onSearch={(searchTerm) => setFilter(searchTerm)} />
      <div className="d-flex flex-wrap sp-body">
        <DogCardsDisplayed petData={filteredData} />
      </div>
    </>
  );
}

export default SearchPage;

试试这个解决方案。修改你的
App.js
文件。我认为您遇到了竞争条件,您必须安装
react async hook

import { useAsync } from 'react-async-hook';

function App() {

  fetchPetData = () => {
      return  axios
      .get(`${BACK_PORT}/data`)
      .then(function (response) {
        return response.data
      })
      .catch(function (error) {
        console.log(error);
        Swal.fire("Oops...", error.response.data, "error");
      });
  }

  const value = useAsync(fetchPetData);
  
  return (
    <div className="App">
      <PetDataContext.Provider value={{ value }}>
        <BrowserRouter>
          <NavBar />
          <Switch>
            <Route path="/" component={MainSignedOut} exact />
            <Route path="/mainsignedin" component={MainSignedIn} />
            <Route path="/searchpage" component={SearchPage} />
            <Route path="/mypets" component={MyPets} />
            <Route path="/admin" component={Admin} />
            <Route exact path="/pets/:id" component={PetPage} />
            <Route component={err404} />
          </Switch>
        </BrowserRouter>
      </PetDataContext.Provider>
    </div>
  );
}
从'react async hook'导入{useAsync};
函数App(){
fetchPetData=()=>{
返回轴
.get(`${BACK\u PORT}/data`)
.然后(功能(响应){
返回响应.data
})
.catch(函数(错误){
console.log(错误);
Swal.fire(“Oops…”,error.response.data,“error”);
});
}
const value=useAsync(fetchPetData);
返回(
);
}
试试这个:

function App() {
  const [petData, setPetData] = useState([]);
  useEffect(() => {
    axios
      .get(`${BACK_PORT}/data`)
      .then(function (response) {
        setPetData(response.data);
      })
      .catch(function (error) {
        console.log(error);
        Swal.fire("Oops...", error.response.data, "error");
      });
  }, []);
  console.log(petData);
  return petData ? (
    <div className="App">
      <PetDataContext.Provider value={{ petData }}>
        <BrowserRouter>
          <NavBar />
          <Switch>
            <Route path="/" component={MainSignedOut} exact />
            <Route path="/mainsignedin" component={MainSignedIn} />
            <Route path="/searchpage" component={SearchPage} />
            <Route path="/mypets" component={MyPets} />
            <Route path="/admin" component={Admin} />
            <Route exact path="/pets/:id" component={PetPage} />
            <Route component={err404} />
          </Switch>
        </BrowserRouter>
      </PetDataContext.Provider>
    </div>
  ) : (
    "Loading pets..."
  );
}
函数应用程序(){
const[petData,setPetData]=useState([]);
useffect(()=>{
axios
.get(`${BACK\u PORT}/data`)
.然后(功能(响应){
setPetData(response.data);
})
.catch(函数(错误){
console.log(错误);
Swal.fire(“Oops…”,error.response.data,“error”);
});
}, []);
console.log(petData);
返回数据(
) : (
“装载宠物…”
);
}
工作原理
这里的想法是,由于网络调用是同步的(它们并发运行,您无法判断它们何时执行),因此您只需观察将被更新的
petData
状态,并在
petData
状态持有有效值时显示实际内容。在此之前,您可以显示一些基本的加载程序,比如您在网站上看到的那种,可能是微调器或其他东西。

您有多确定您需要上下文API来完成您要完成的任务?您正在尝试访问和记录
petData[0]。name
petData
之前包含任何数据。您希望编写的组件不尝试访问不存在的数据,并且可能会重写它以处理这种情况,并呈现某种回退UI,直到它具有要呈现的数据。因此,最好不要使用上下文吗?React文档禁止使用它,除非有必要,因为它增加了复杂性和一些性能考虑因素。请参阅。如果将初始状态更改为null而不是[],则此操作有效。谢谢很好,您还可以执行
返回petData.length?():“加载”
如果必须将状态初始化为空数组。
import { useAsync } from 'react-async-hook';

function App() {

  fetchPetData = () => {
      return  axios
      .get(`${BACK_PORT}/data`)
      .then(function (response) {
        return response.data
      })
      .catch(function (error) {
        console.log(error);
        Swal.fire("Oops...", error.response.data, "error");
      });
  }

  const value = useAsync(fetchPetData);
  
  return (
    <div className="App">
      <PetDataContext.Provider value={{ value }}>
        <BrowserRouter>
          <NavBar />
          <Switch>
            <Route path="/" component={MainSignedOut} exact />
            <Route path="/mainsignedin" component={MainSignedIn} />
            <Route path="/searchpage" component={SearchPage} />
            <Route path="/mypets" component={MyPets} />
            <Route path="/admin" component={Admin} />
            <Route exact path="/pets/:id" component={PetPage} />
            <Route component={err404} />
          </Switch>
        </BrowserRouter>
      </PetDataContext.Provider>
    </div>
  );
}
function App() {
  const [petData, setPetData] = useState([]);
  useEffect(() => {
    axios
      .get(`${BACK_PORT}/data`)
      .then(function (response) {
        setPetData(response.data);
      })
      .catch(function (error) {
        console.log(error);
        Swal.fire("Oops...", error.response.data, "error");
      });
  }, []);
  console.log(petData);
  return petData ? (
    <div className="App">
      <PetDataContext.Provider value={{ petData }}>
        <BrowserRouter>
          <NavBar />
          <Switch>
            <Route path="/" component={MainSignedOut} exact />
            <Route path="/mainsignedin" component={MainSignedIn} />
            <Route path="/searchpage" component={SearchPage} />
            <Route path="/mypets" component={MyPets} />
            <Route path="/admin" component={Admin} />
            <Route exact path="/pets/:id" component={PetPage} />
            <Route component={err404} />
          </Switch>
        </BrowserRouter>
      </PetDataContext.Provider>
    </div>
  ) : (
    "Loading pets..."
  );
}