【问题标题】:React useEffect stop infinite loopReact useEffect 停止无限循环
【发布时间】:2021-10-21 01:27:20
【问题描述】:

这段代码造成了一个无限循环,我需要想办法解决它。

我想用 moviesData 值填充状态电影信息,以便能够将其映射到每部电影的显示卡。

首先,我尝试在推送功能之后设置Movieinfos,但它不起作用。 所以我觉得把它放到一个独立的useEffect中会更好。

这似乎不是正确的方法^^。

function App() {

  const [movieid, setMovieid] = useState([]);
  const [movieinfos, setMovieinfos] = useState([]);
  let moviesData = [] 

useEffect(() => {
  axios.get('http://localhost:5000')
  .then(function (response) {
    // handle success
    console.log(response.data.movies)
   
      setMovieid(response.data.movies)
  })

  .catch(function (error) {
    // handle error
    console.log(error);
  })
     
  
}, []);

console.log(movieid)

useEffect(() => {
for (const movie of movieid) {
console.log(movie.movieid)
 axios.get(`${BASE_URL}${movie.movieid}?api_key=${API_KEY}&language=fr`) 

  .then(function (response) {
    // handle success
    
    
    moviesData.push(
    {Genres: response.data.genres,
      Overview: response.data.overview,
      Poster: response.data.poster_path,
      Company: response.data.production_companies,
      Release: response.data.release_date,
      Title: response.data.title}
      );
              
  })
  .catch(function (error) {
    // handle error
    console.log(error);
  })

  }

}, [movieid]);

useEffect(() => {

setMovieinfos (moviesData)
 
}, [moviesData]);

  return (
    <div className="App">
      <div className="Header">
        <Logo />
      </div>
      <div className="Menu">
        <Search />
        <Add_movie_button />
        <Delete_movie_button />
        <Random_movie_button />
      </div>
      <div className="Movies">
        
        
        {movieinfos.map((movie) => <Movie_card key={movie.Title} data={movie}/>)}

      </div>
      
    </div>
  );
}

export default App;

【问题讨论】:

  • let moviesData = [] 是每个渲染上的 new 数组,但最后一个 useEffect 取决于它。这意味着它还将在每次渲染时运行并更新状态 (setMovieinfos)。这是你的无限循环。为了帮助摆脱这种情况,我需要更好地了解您要做什么。您能否澄清您的问题并可能添加一些虚拟数据?
  • 第一个 axios 从我的数据库中获取 ID。第二个 axios 使用这些 ID 向“电影数据库”发出请求,以收集每部电影的信息。我想要做的是为每部电影渲染一个卡片组件,其中包含电影信息。我做所有这些事情是因为我只想要来自 API 的数据库中的电影的信息。
  • 是否有理由不在一次操作中执行此操作?
  • 我尝试直接 setState 而不是将东西放入moviesData表中,但它不起作用
  • Olivarra 解决方案有效,感谢您的帮助 :)

标签: javascript reactjs use-effect


【解决方案1】:

正如 Yohsi 所指出的,无限循环是由 useEffect 引起的,这取决于每次重新渲染时的新数组。

不过,我的建议是,您应该尽量让组件保持尽可能少的状态。

如果您不需要在任何地方显示movieid,请不要将其设置为稍后由 useEffect 处理的状态,这只会让人难以理解。

看起来你的整个组件只需要moviesInfo 状态,你可以在一个useEffect中处理它:

const [movieinfos, setMovieinfos] = useState([]);

useEffect(() => {
  axios
    .get("http://localhost:5000")
    .then(function (response) {
      const movies = response.data.movies;
      return Promise.all(
        movies.map((movie) =>
          axios.get(
            `${BASE_URL}${movie.movieId}?api_key=${API_KEY}&language=fr`
          )
        )
      );
    })
    .then((responses) => {
      setMovieinfos(
        responses.map((response) => ({
          Genres: response.data.genres,
          Overview: response.data.overview,
          Poster: response.data.poster_path,
          Company: response.data.production_companies,
          Release: response.data.release_date,
          Title: response.data.title,
        }))
      );
    });
}, []);

我建议在使用 react 时避免使用许多 useEffect 钩子,特别是避免使用它们来编排相互依赖的副作用。

【讨论】:

  • 成功了,非常感谢!!我必须检查 Promise.all 是如何工作的,我不知道那件事 ^^
猜你喜欢
  • 2022-11-29
  • 2021-01-31
  • 2020-04-14
  • 2021-12-05
  • 2022-12-02
  • 2020-09-06
  • 2020-09-29
  • 2019-08-15
相关资源
最近更新 更多