如何使用从一个类到另一个类的状态

时间:2019-09-19 12:50:45

标签: javascript node.js reactjs

因此,我目前正在使用在线提供的PokeApi开发PokeDex。

该项目的代码如下:

import React, { Component } from "react";
import PokemonCard from "./PokemonCard";
import "../ui/PokemonList.css";
import axios from "axios";

export const PokemonList = class PokemonList extends Component {
  state = {
    url: "https://pokeapi.co/api/v2/pokemon/",
    pokemon: null
  };

  async componentDidMount() {
    const res = await axios.get(this.state.url);
    this.setState({ pokemon: res.data["results"] });

    console.log(res);
  }

  render() {
    return <div></div>;
  }
};
export const PokeList = () => {
  return (
    <React.Fragment>
      {this.state.pokemon ? (
        <section className="poke-list">
          {this.state.pokemon.map(pokemon => (
            <PokemonCard />
          ))}
        </section>
      ) : (
        <h1>Loading Pokemon</h1>
      )}
    </React.Fragment>
  );
};

如您所见,我已经在PokemonList Component类中声明了一个状态,但是随后我尝试在变量PokeList中进一步调用它。问题是在PokeList

中无法识别状态

(我收到错误消息“ TypeError:无法读取未定义的属性'state'”)

我该如何调用上面的类中声明的状态?

-------------------编辑--------------------------- ----

好的,所以我意识到了一些。我有Dashboard.js的代码,该代码显示了我的列表。代码如下

import React, { Component } from "react";

import { PokeList } from "../pokemon/PokemonList";

export default class Dashboard extends Component {
  render() {
    return (
      <div>
        <div className="row">
          <div className="col">
            <PokeList />
          </div>
        </div>
      </div>
    );
  }
}

当我将代码从PokeList更改为PokemonList时。所以会

import React, { Component } from "react";

import { PokemonList } from "../pokemon/PokemonList";

export default class Dashboard extends Component {
  render() {
    return (
      <div>
        <div className="row">
          <div className="col">
            <PokemonList />
          </div>
        </div>
      </div>
    );
  }
}

我认为可以从Api那里获得20只神奇宝贝的清单

console.log(this.state.pokemon);。

但是由于我没有在仪表板上显示PokeList,所以所有的Pokemon卡都不会显示。

控制台输出的屏幕截图

enter image description here

4 个答案:

答案 0 :(得分:2)

首先,所有功能组件都是无状态的。如果需要维护状态,请使用类组件或挂钩。您不能在另一个组件中使用一个组件的状态。您有两个选择,

  1. 在这些组件之间创建父子关系
  2. 使用状态管理库(Redux等)

答案 1 :(得分:1)

PokemonList和PokeList组件之间有些混淆。我相信您真正想要的只是其中之一。如果将两者混合使用,则可以有一个根据状态控制视图的组件,在这种情况下,状态就是“口袋妖怪”列表。

我在这里混合了两者,因此您的render方法将渲染“ Loading Pokemon”,直到您从axios返回响应为止,然后在响应返回时,它将获取该数据,更新您的状态,并且状态更新触发重新渲染。

import React, { Component } from "react";
import PokemonCard from "./PokemonCard";
import axios from "axios";

class PokemonList extends Component {
  state = {
    url: "https://pokeapi.co/api/v2/pokemon/",
    pokemon: null
  };

  componentDidMount() {
    axios.get(this.state.url).then(res => {
      this.setState({ pokemon: res.data["results"] });
    });
  }

  render() {
    let pokemonList = <h1>Loading Pokemon</h1>;

    const pokemons = this.state.pokemon;

    if (pokemons) {
      pokemonList = (
        <section className="poke-list">
          <ul>
            {pokemons.map(pokemon => (
              <PokemonCard pokemon={pokemon} />
            ))}
          </ul>
        </section>
      );
    }

    return <React.Fragment>{pokemonList}</React.Fragment>;
  }
}

export default PokemonList;

我还创建了一个简单的PokemonCard组件,在其中列出了API的结果,只是向您展示该方法有效。

import React from "react";

const pokemonCard = props => {
  return (
    <li key={props.pokemon.name}>
      <a href={props.pokemon.url}>{props.pokemon.name}</a>
    </li>
  );
};

export default pokemonCard;

您可以找到最终的代码,现在将PokeList和PokemonList组合到一个称为PokemonList的组件中:

Edit shy-pine-de969

请记住,如果您的渲染功能依赖于某个状态,则可以确定应该在该组件中管理该状态,或者从父组件中传递该状态。

在您的示例中,我注意到您在状态内设置了url。 URL确实不会改变。这是一个常数,因此您可以轻松地将其从状态中删除并将其放置在变量中,然后只将口袋妖怪列表保留在那里。

例如:

const url = "https://pokeapi.co/api/v2/pokemon/";
state = {
    pokemon: null
  };

  componentDidMount() {
    axios.get(url).then(res => {
      this.setState({ pokemon: res.data["results"] });
    });
  }

答案 2 :(得分:0)

import  React , { Component } from "react";
import axios from "axios";
//make it as class based component
export default class PokemonList extends Component {
  state = {
    url: "https://pokeapi.co/api/v2/pokemon/",
    pokemon: null
  };

  async componentDidMount() {
    const res = await axios.get(this.state.url);
    this.setState({ pokemon: res.data["results"] });

    console.log(res);
  }

  render() {
    //check your data here 
     console.log(this.state.pokemon)
    {/*pass data to child*/}
    return <div> <PokeList data = { this.state } /> </div>;
  }
};

//export this component
export const PokeList = (props) => {
//check your data is coming or not
console.log(props.data)
//access your data from props
  return (
    <React.Fragment>
      {props.data.pokemon ? (
        <section className="poke-list">
          {props.data.pokemon.map(pokemon => (
               pokemon.name
          ))}
        </section>
      ) : (
        <h1>Loading Pokemon</h1>
      )}
    </React.Fragment>
  );
};

答案 3 :(得分:0)

您需要迭代自己的清单,将结果从componentDidMount函数作为道具传递给子组件,然后在子组件Demo

中接收道具。