关于路由(链接)和React中的异步获取数据

时间:2019-07-24 19:17:17

标签: javascript reactjs api axios fetch

首先,晚上好。我想在React上提高自己。所以我正在研究Starwars项目s‍?。

我有两个问题。 首先,我在角色详细信息页面的底部列出了不同的角色。同样,我希望通过同一组件将其定向到不同的字符。但是,即使链接更改,我的组件也不会刷新。但是情况正在改变?。

注意: 沙盒链接:https://codesandbox.io/s/github/kasim444/Javascript-Camp-2019/tree/master/challenges/star-wars-app/

我的项目github链接:https://github.com/kasim444/Javascript-Camp-2019/tree/master/challenges/star-wars-app/


// component that I redirect in.

class CharacterDetail extends Component {

  render () {
    const characterId = this.props.match.params.id;
    const {
      name,
      height,
      mass,
      hair_color,
      skin_color,
      eye_color,
      birthday_year,
      gender,
      homeworld,
      loading,
    } = this.state;
    return loading
      ? <Loading />
      : (
        <div>
          <main className="characterBg">
            <DetailHeader imgLink={characterAvatarLink[characterId - 1]} />
            <CharacterContent
              imgLink={characterAvatarLink[characterId- 1]}
              characterInfo={this.state}
            />
          </main>
          <FeaturedCharacters />
        </div>
      );
  }
}

// feautered character component 
function FeaturedCharacters () {
  const [characters, setCharacters] = useState ([]);
  const [loading, setLoading] = useState (true);

  const fetchCharacters = async () => {
    const data = await fetch ('https://swapi.co/api/people/');
    const fetchPeople = await data.json ();
    const feauteredCharacter = fetchPeople.results.filter (
      (character, index) => index < 4
    );
    setCharacters (feauteredCharacter);
    setLoading (false);
  };
  useEffect (() => {
    fetchCharacters ();
  }, []);

  return (
    <div>
      <h2>Popular Characters</h2>
      <div className="d-flex-row container">
        {loading
          ? <PlaceholderDiv />
          : characters.map ((character, index) => (
            <CharacterCard
              key={character.name}
              chaId={index + 1}
              chaDet={character.name}
              imgLink={characterAvatarLink[index]}
            />
            ))}
      </div>
    </div>
  );
}

// character card link component
const CharacterCard = props => {
  const name = props.chaDet;
  return (
    <Link className="profile_card" to={`/character/${props.chaId}`}>
      <div className="profile_image">
        <img src={props.imgLink} alt={name} />
      </div>
      <div className="profile_content">
        <h3>{name}</h3>
        <div className="read_more d-flex-row">
          <img src={showIcon} alt="Show Icon" />
          &nbsp;Show More
        </div>
      </div>
    </Link>
  );
};



// main component
const App = () => {
  return (
    <Router>
      <div className="st-container d-flex-column">
        <Header />
        <Switch>
          <Route exact path="/" component={HomePage} />
          <Route path="/movie/:title" component={MovieDetails} />
          <Route path="/character/:id" component={CharacterDetail} />
          <Route
            path="/githubProfile"
            component={() => {
              window.location.href = 'https://github.com/kasim444/Javascript-Camp-2019/tree/master/challenges/star-wars-app';
              return null;
            }}
          />
        </Switch>
        <Footer />
      </div>
    </Router>
  );
};


第二个问题是我从Api的数据中提取了数据。我可以看到人物的轮廓。现在正在工作。但是我感觉有些不对劲。?如何改善Axios中的Fetch操作?

  async componentDidMount () {
    const characterId = this.props.match.params.id;
    const filmSeries = [];
    const characterDetail = await axios.get (
      `https://swapi.co/api/people/${characterId}/`
    );


    const filmsFetchLinks = characterDetail.data.films;

    const promisesData = await filmsFetchLinks.map(link => axios.get(link));
    axios.all (promisesData).then(value => {
      value.map (val => filmSeries.push (val.data.title));
      let {
        name,
        height,
        mass,
        hair_color,
        skin_color,
        eye_color,
        birthday_year,
        gender,
        homeworld,
        films,
      } = characterDetail.data;

      fetch(homeworld).then(home => home.json()).then(val => this.setState({homeworld: val.name}));


      this.setState ({
        name,
        height,
        mass,
        hair_color,
        skin_color,
        eye_color,
        birthday_year,
        gender,
        films: filmSeries,
        loading: false,
      });
    });
  }

对不起,如果您无聊。似乎有点长,因为组件是相互连接的。预先感谢您的关注。 ?

1 个答案:

答案 0 :(得分:0)

您可以使用componentDidUpdate并将当前参数ID与上一个参数进行比较(您必须将其保存为状态),然后再次获取数据(如果两者不同)。每当路线更改时,componentDidUpdate都会消失。

更好的方法是使用useEffect并取决于参数id。在使用效果中,您需要进行所有数据提取。像这样:

 const { id: characterId } = props.match.params;

 React.useEffect(() => {
    async function getData() {
       // fetch all you data here
    }
    getData();
  }, [characterId]);

您可以在此处看到其原始版本: https://codesandbox.io/s/star-wars-app-sx8hk