Javascript React钩子组件在API调用之前呈现

Javascript React钩子组件在API调用之前呈现,javascript,reactjs,Javascript,Reactjs,我需要创建一个React应用程序,让你列出口袋妖怪和类型。 我从PokeAPI获取数据。从应用程序组件获取数据然后将其传递给子组件是一种好的做法,还是从子组件获取数据更好 我在主应用程序中获取数据,我可以看到获取工作,因为我使用console.log记录数据,但我的组件没有获取数据,因此我获取了一个props.map,它不是中的函数 这是我的App.js: import React, { useState } from "react"; import logo from &q

我需要创建一个React应用程序,让你列出口袋妖怪和类型。 我从PokeAPI获取数据。从应用程序组件获取数据然后将其传递给子组件是一种好的做法,还是从子组件获取数据更好

我在主应用程序中获取数据,我可以看到获取工作,因为我使用console.log记录数据,但我的组件没有获取数据,因此我获取了一个props.map,它不是中的函数

这是我的App.js:

import React, { useState } from "react";
import logo from "./logo.svg";
import "./App.css";
import axios from "axios";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import PokemonList from "./components/PokemonList";

const App = (props) => {
  const [pokemons, setPokemons] = useState([]);

  const [types, setTypes] = useState([]);

  const [isLoading, setIsLoading] = useState(true);

  const getPokemons = () => {
    const axios = require("axios").default;
    axios.get("https://pokeapi.co/api/v2/pokemon").then(function (response) {
      console.log("Fetched pokemons");
      console.log(response.data.results);
      setIsLoading(false);
      setPokemons(response.data.results);
    });
  };

  const getTypes = () => {
    setIsLoading(true);
    const axios = require("axios").default;
    axios.get("https://pokeapi.co/api/v2/type").then(function (response) {
      console.log("Fetched types");
      console.log(response.data.results);
      setIsLoading(false);
      setTypes(response.data.results);
    });
  };

  return (
    <Router>
      <div>
        <nav>
          <ul>
            <li>
              <Link to="/pokemons" onClick={getPokemons}>
                Pokemons
              </Link>
            </li>
            <li>
              <Link to="/types">Types</Link>
            </li>
          </ul>
        </nav>

        {/* A <Switch> looks through its children <Route>s and
            renders the first one that matches the current URL. */}
        <Switch>
          <Route path="/pokemons">
            <Pokemons pokemons={pokemons} />
          </Route>
          <Route path="/types">
            <Types />
          </Route>
        </Switch>
      </div>
    </Router>
  );
};

function Pokemons(pokemons) {
  return <PokemonList props={pokemons} />;
}

function Types(typeList) {
  return <h2>TYPES:</h2>;
}

export default App;
import React,{useState}来自“React”;
从“/logo.svg”导入徽标;
导入“/App.css”;
从“axios”导入axios;
从“react Router dom”导入{BrowserRouter as Router,Switch,Route,Link};
从“/components/PokemonList”导入PokemonList;
常量应用=(道具)=>{
const[pokemons,setPokemons]=useState([]);
const[types,setTypes]=useState([]);
const[isLoading,setIsLoading]=useState(true);
const getPokemons=()=>{
const axios=require(“axios”)。默认值;
axios.get(“https://pokeapi.co/api/v2/pokemon)然后(函数(响应){
log(“抓取的口袋妖怪”);
日志(响应、数据、结果);
设置加载(假);
setPokemons(response.data.results);
});
};
const getTypes=()=>{
设置加载(真);
const axios=require(“axios”)。默认值;
axios.get(“https://pokeapi.co/api/v2/type)然后(函数(响应){
log(“获取的类型”);
日志(响应、数据、结果);
设置加载(假);
集合类型(响应、数据、结果);
});
};
返回(
  • 口袋妖怪
  • 类型
{/*A查看其子对象和 呈现与当前URL匹配的第一个URL.*/} ); }; 功能口袋妖怪(口袋妖怪){ 返回; } 功能类型(类型列表){ 返回类型:; } 导出默认应用程序;
这是我的PokemonList.js:

import React from "react";
import { Card } from "semantic-ui-react";
import PokeCard from "./PokeCard";

const Pokemonlist = (props) => {
  let content = (
    <Card.Group>
      {props.map(function (object, i) {
        return <PokeCard pokemon={object} key={i} />;
      })}
    </Card.Group>
  );

  return content;
};

export default Pokemonlist;

从“React”导入React;
从“语义ui react”导入{Card};
从“/PokeCard”导入PokeCard;
常量口袋妖怪列表=(道具)=>{
让内容=(
{props.map(函数(对象,i){
返回;
})}
);
返回内容;
};
导出默认口袋妖怪列表;
最后一个是我的PokeCard.js

import { Card, Image } from "semantic-ui-react";
import React from "react";

const PokeCard = (pokemon) => {
  let content = (
    <Card>
      <Card.Content>
        <Image floated="right" size="mini" src={pokemon.img} />
        <Card.Header>{pokemon.name}</Card.Header>
        <Card.Meta>{pokemon.base_experience}</Card.Meta>
        <Card.Description>ID: {pokemon.id}</Card.Description>
      </Card.Content>
    </Card>
  );

  return content;
};

export default PokeCard;

从“语义ui”导入{Card,Image};
从“React”导入React;
const PokeCard=(口袋妖怪)=>{
让内容=(
{pokemon.name}
{pokemon.base_experience}
ID:{pokemon.ID}
);
返回内容;
};
导出默认PokeCard;
因此,基本思想是:

在主页上,单击Pokemons按钮,该按钮调用fetch,然后呈现PokemonList组件,该组件基本上只呈现我获取的数据中的多个PokeCard组件

1、我在这里错过了什么

2、在我的情况下,如果没有任何变化,我需要使用useEffect吗

3、我应该什么时候取数据,在哪里取


编辑:我想将钩子与零类一起使用

  • 最好在父级中获取一些初始数据,然后在子级中发出进一步的请求 组件(如果需要)以保存网络使用情况
  • 在渲染元素之前,使用
    useffect
    钩子获取结果
  • 您缺少的是您没有在口袋妖怪中使用道具,您应该将get调用放在
    App
    组件中的useffect钩子中,因为子组件在道具传递给它之前正在渲染,这就是您得到
    未定义的
    错误的原因

    • 以下是我的答案摘要

      • 最好在父级中获取一些初始数据,然后在子级中发出进一步的请求 组件(如果需要)以保存网络使用情况
      • 在渲染元素之前,使用
        useffect
        钩子获取结果
      • 您缺少的是您没有在口袋妖怪中使用道具,您应该将get调用放在
        App
        组件中的useffect钩子中,因为子组件在道具传递给它之前正在渲染,这就是您得到
        未定义的
        错误的原因

      在PokemonList.js中,您已经在
      道具上运行了地图功能。但是你应该在
      props.pokemons
      @Shuvo上运行map函数,现在我得到了这个错误消息:无法读取未定义的属性“map”,因为声明你映射的是props而不是pokemons,你还需要在进行map之前检查undefined/null,因为最初它是未定义的,因为API调用不是立即的。我建议您在子组件中使用“useEffect”来获取并确保列表在映射之前的任何状态下都不是未定义的/null。在PokemonList.js中,您已经在
      道具上运行了map函数。但是你应该在
      props.pokemons
      @Shuvo上运行map函数,现在我得到了这个错误消息:无法读取未定义的属性“map”,因为声明你映射的是props而不是pokemons,你还需要在进行map之前检查undefined/null,因为最初它是未定义的,因为API调用不是立即的。我建议您在子组件中使用“useEffect”来获取并确保列表在映射之前的任何状态下都不是未定义的/null。啊,我明白了,非常感谢!那么它在抓取完成后重新呈现我的页面?这是否意味着我应该在每个组件上设置一些初始加载页面?如果数据不为空,我可以签入其他组件吗?我知道一种方法:{props.pokemons&&PokeList>,但在这个钩子设置中,它似乎对我不起作用。检查这些道具是否在子组件中的return语句之前,如thisprops.pokemon?:啊,我明白了,非常感谢!所以当获取完成时它会重新呈现我的页面?