单击依赖项时不触发 useEffect

时间:2021-06-27 09:32:16

标签: javascript reactjs react-hooks use-effect

我有一个按钮可以触发从 fetchDataHandler 获取数据,它与 useEffect 一起使用,它还可以在页面加载时获取数据。但是,当我将 addMovieHandler 作为依赖项添加到 useEffect 以在添加另一部电影时自动获取数据时,它就不起作用了。所以我发现我可能用错了,但无法弄清楚。

const App = () => {
  const [movies, setMovies] = useState([]);
  const [isLoading, setIsLoading] = useState(false);

  const fetchDataHandler = useCallback(async () => {
    setIsLoading(true);
    const respone = await fetch(
      "https://react-http-3af47-default-rtdb.firebaseio.com/movies.json"
    );
    if (!respone.ok) {
      setIsLoading(false);
      throw new Error("Something went wrong!");
    }
    const data = await respone.json();
    const movieList = [];

    for (const key in data) {
      movieList.push({
        id: key,
        title: data[key].title,
        text: data[key].text,
      });
    }

    setMovies(movieList);
    setIsLoading(false);
  }, []);

  const addMovieHandler = useCallback(async (movie) => {
    const respone = await fetch(
      "https://react-http-3af47-default-rtdb.firebaseio.com/movies.json",
      {
        method: "POST",
        body: JSON.stringify(movie),
        headers: {
          "Content-Type": "application/json",
        },
      }
    );
    const data = await respone.json();
    console.log(data);
  }, []);

  useEffect(() => {
    fetchDataHandler();
  }, [fetchDataHandler, addMovieHandler]);

  let content = <p>no movies found</p>;

  if (movies.length > 0) {
    content = <MovieList movies={movies} />;
  }
  if (isLoading) {
    content = <p>loading...</p>;
  }

  return (
    <React.Fragment>
      <UserInput onAddMovie={addMovieHandler}></UserInput>
      <Card>
        <button onClick={fetchDataHandler}>Fetch movies</button>
      </Card>
      {content}
    </React.Fragment>
  );
};

export default App;

2 个答案:

答案 0 :(得分:1)

试试这个:

addMovieHandler 中删除 useEffect。当您点击 addMovieHandler 时,它无论如何都会获取数据。因此,您可以在处理程序本身中使用最新响应设置电影,如下所示:

setMovies(...data)

这将用新获取的电影列表替换电影列表。如果您想添加到旧列表中,您可以这样做:

setMovies([...movies, data])

这是将新获取的列表连接到已经存在的电影列表并更新变量并重新渲染电影列表部分。

答案 1 :(得分:1)

您的 useEffect 不会在 addMovieHandler 引用更改时触发,因为您使用的是没有依赖项(useCallback 第二个参数)的 [] 来记忆它。这意味着 addMovieHandler 引用在重新渲染之间根本不会改变,但您的 useEffect 调用基于它这样做。简而言之 - 如果提供的依赖项具有相同的值(在您的解决方案中就是这种情况),则 useEffect 不会重新运行。

fetchDataHandler 也是如此。

无论如何,这都不是解决问题的好方法。您最好在 movies 本身中成功添加电影时更新您的 addMovieHandler 数组。删除和更新等其他操作也是如此。