简体   繁体   English

将基于 class 的组件重构为功能组件

[英]Refactoring a class based component to a Functional component

TL;DR: I am trying to refactor my class-based App component to a Functional component and I am having some unexpected results with the useEffect Hook. TL;DR:我正在尝试将基于类的 App 组件重构为功能组件,并且使用 useEffect Hook 获得了一些意想不到的结果。

I am fairly new to React and the version of my app to search for movies with the OMDB API was a class based one.我对 React 和我的应用程序版本相当陌生,使用 OMDB API 搜索电影是基于 class 的版本。 It was working well so I wanted to practice some more on working with hooks and context before venturing into redux.它运行良好,所以我想在进入 redux 之前多练习使用钩子和上下文。

In my class component I had the following code:在我的 class 组件中,我有以下代码:

componentDidMount = () => {
    window.onscroll = this.handleScroll;
  };

  handleScroll = () => {
    if (!this.state.movies.loading) {
      if (getScrollDownPercentage(window) > 0.8) {
        const nextPage = this.state.movies.page + 1;
        this.searchMovies(this.state.movies.searchValue, nextPage);
        this.setState({
          ...this.state,
          movies: {
            ...this.state.movies,
            page: nextPage,
          },
        });
      }
    }
  };

  searchMovies = (str, page = 1) => {
    const existingMovies =
      this.state.movies.data.length && this.state.movies.searchValue === str
        ? this.state.movies.data
        : [];
    this.setState({
      ...this.state,
      movies: {
        ...this.state.movies,
        loading: true,
      },
    });
    axios
      .get(`${process.env.REACT_APP_ENDPOINT}s=${str}&page=${page}`)
      .then((response) => {
        if (response.data.Response === "True") {
          this.setState({
            ...this.state,
            movies: {
              ...this.state.movies,
              loading: false,
              searchValue: str,
              data: [...existingMovies, ...response.data.Search],
            },
          });
        }
      });
  };

After the refactor I have following code which feels less clean (so the opposite of what I was hoping to achieve)在重构之后,我的代码感觉不太干净(所以与我希望实现的相反)

The moment I reach the end of the page I get a non-stop stream of axios calls switching between page 2 and 3当我到达页面末尾的那一刻,我得到一个不停的 axios 调用的 stream 调用在第 2 页和第 3 页之间切换

If I'm not wrong it's not working because setState is running asynchronously and I am getting constant updates on my page.如果我没记错的话,它不起作用,因为 setState 正在异步运行,并且我的页面上不断更新。

  useEffect(() => {
    window.onscroll = () => {
      handleScroll();
    };
    if (searchValue) {
      console.log(page);
      searchMovies(searchValue, page);
    }
    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  }, [searchValue, page]);

  const handleScroll = () => {
    if (!loading && searchValue) {
      if (getScrollDownPercentage(window) > 0.7) {
        setState({
          ...state,
          movies: {
            ...state.movies,
            page: page + 1,
          },
        });
      }
    }
  };

  const searchMovies = (str, page = 1) => {
    const existingMovies = data.length && prevSearchValue === str ? data : [];
    setState({
      ...state,
      movies: {
        ...state.movies,
        loading: true,
      },
    });
    axios
      .get(`${process.env.REACT_APP_ENDPOINT2}s=${str}&page=${page}`)
      .then((response) => {
        if (response.data.Response === "True") {
          setState({
            ...state,
            movies: {
              ...state.movies,
              loading: false,
              searchValue: str,
              data: [...existingMovies, ...response.data.Search],
            },
          });
        } else {
          setState({
            ...state,
            movies: {
              ...state.movies,
              loading: false,
              error: true,
            },
          });
        }
      });
  };

I hope I included everything (and also not too much) to make my clear my problem.我希望我包括所有内容(也不要太多)以明确我的问题。 Looking out for some React wizards.寻找一些 React 向导。

Edit: specified problem a little bit more and put it in bold编辑:指定问题多一点,并用粗体表示

Given your reply, I think what you'd want to do multiple useEffects : one for searchMovies and one for the scroll setup.鉴于您的回复,我认为您想要执行多个useEffects :一个用于 searchMovies,另一个用于滚动设置。

useEffect(() => {
  window.onscroll = () => {
     handleScroll();
  };
  return () => {
    window.removeEventListener("scroll", handleScroll);
  };
}, []);

useEffect(() => {
  if (searchValue) {
    console.log(page);
    searchMovies(searchValue, page);
  }
}, [searchValue, page])

A quick fix will be use an empty array as the second argument to avoid infinite loop快速修复将使用空数组作为第二个参数以避免无限循环

useEffect(() => {
    //your code
  },[]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM