使用useEffect在React中重新获取数据

时间:2020-11-01 21:06:00

标签: reactjs axios react-hooks use-effect

我希望有人可以帮助我解决重新获取数据时遇到的问题。在初始页面渲染上,我正在获取显示有关随机电影的信息的数据,然后,当用户单击页面上的“下一步”按钮时,将显示新的随机电影。我遇到的问题是,它似乎重新获取了两次数据,这意味着单击一次按钮时,会弹出一秒钟的新电影,然后是另一段。 >

经过数小时的搜寻后,我似乎无法找到此问题的确切解决方案,但我怀疑这是我使用useEffect挂钩的方式:

    const Movie = () => {
     const [pageNo, setPageNo] = useState(1);
 const [movieNo, setMovieNo] = useState(1);
 const [movie, setMovie] = useState('');
 const [isLoading, setIsLoading] = useState(true);
 const [imageUrl, setImageUrl] = useState('https://image.tmdb.org/t/p/');

 function handleClick(e) {
  e.preventDefault();
  setMovieNo(Math.floor(Math.random() * 20));
  setPageNo(Math.floor(Math.random() * 500 + 1));
 }

 async function fetchData(page) {
  const result = await axios(
   `https://api.themoviedb.org/3/discover/movie?api_key=a035c9128c767a8b70c9413632d63cd0&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=${page}&vote_average.gte=1.0`
  );
  setMovie(result.data.results);
  setIsLoading(false);
 }

 useEffect(() => {
  fetchData(pageNo);
 }, [pageNo]);
    
     return (
      ...
     );
    };

很抱歉,如果这个问题不是很清楚,我从来都不擅长于解释问题

1 个答案:

答案 0 :(得分:0)

罪魁祸首是此功能。 两次更改状态(movieNo,pageNo分别更改一次)会使页面呈现两次。

 function handleClick(e) {
  e.preventDefault();
  setMovieNo(Math.floor(Math.random() * 20));
  setPageNo(Math.floor(Math.random() * 500 + 1));
 }

完成示例代码以重现问题

import React, { useState, useEffect } from "react";
import axios from "axios";

const Movie = () => {
  const [pageNo, setPageNo] = useState(1);
  const [movieNo, setMovieNo] = useState(1);
  const [movie, setMovie] = useState("");
  const [isLoading, setIsLoading] = useState(true);
  const [imageUrl, setImageUrl] = useState("https://image.tmdb.org/t/p/");

  function handleClick(e) {
    e.preventDefault();
    setMovieNo(Math.floor(Math.random() * 20));
    setPageNo(Math.floor(Math.random() * 500 + 1));
  }

  async function fetchData(page) {
    const result = await axios(
      `https://api.themoviedb.org/3/discover/movie?api_key=a035c9128c767a8b70c9413632d63cd0&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=${page}&vote_average.gte=1.0`
    );
    setMovie(result.data.results);
    setIsLoading(false);
  }

  useEffect(() => {
    fetchData(pageNo);
  }, [pageNo]);

  return (
    <div>
      <p>{isLoading ? "" : movie[movieNo].title}</p>
      <button onClick={handleClick}>next</button>
    </div>
  );
};

export default Movie;

在此处修复

  1. 单个对象的组合状态
 const [rank, setRank] = useState({ pageNo: 1, movieNo: 1 });

  setRank({
      pageNo: Math.floor(Math.random() * 500 + 1),
      movieNo: Math.floor(Math.random() * 20)
    });

修复后完成代码。

import React, { useState, useEffect } from "react";
import axios from "axios";

const Movie = () => {
  const [rank, setRank] = useState({ pageNo: 1, movieNo: 1 });
  const [movie, setMovie] = useState("");
  const [isLoading, setIsLoading] = useState(true);
  const [imageUrl, setImageUrl] = useState("https://image.tmdb.org/t/p/");

  function handleClick(e) {
    e.preventDefault();
    setRank({
      pageNo: Math.floor(Math.random() * 500 + 1),
      movieNo: Math.floor(Math.random() * 20)
    });
  }

  async function fetchData(page) {
    setIsLoading(true);
    const result = await axios(
      `https://api.themoviedb.org/3/discover/movie?api_key=a035c9128c767a8b70c9413632d63cd0&language=en-US&sort_by=popularity.desc&include_adult=false&include_video=false&page=${page}&vote_average.gte=1.0`
    );
    setMovie(result.data.results);
    setIsLoading(false);
  }

  useEffect(() => {
    fetchData(rank.pageNo);
  }, [rank]);

  return (
    <div>
      <p>{isLoading ? "loading..." : movie[rank.movieNo].title}</p>
      <button onClick={handleClick}>next</button>
    </div>
  );
};

export default Movie;

总而言之,useEffect没有错。 多次更改状态会导致您的组件多次渲染。尝试将所有这些条件合并为一个状态,以便更易于管理。