useEffect 导致无限循环

useEffect is causing an infinite Loop

我遇到了一个无限循环,它不断地从 API 中获取信息。

如果我将 fetchTheMovie() 包装在 if 语句中,问题可以解决,但我不明白原因,有什么想法或更好的解决方案吗?

if (!movie.Title) {
  fetchTheMovie(id);
}

终点是/movie/id

电影组件:

const SingleMovie = (props) => {
  const { id } = useParams();
  const {movie} = props;

  useEffect(() => {
    const {fetchTheMovie} = props;
    fetchTheMovie(id);
  }, []);
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(WithSpinner(SingleMovie));

WithSpinner 组件:

const WithSpinner = (WrappedComponent) => {
  const Spinner = ({ isLoading, ...otherProps }) => {
    return isLoading ? (
      <SpinnerOverlay>
        <SpinnerContainer />
      </SpinnerOverlay>
    ) : (
      <WrappedComponent {...otherProps} />
    );
  };
  return Spinner;
};

使用组件的页面

const Page = ({ loading }) => {
  const { id } = useParams();
  return (
    <div>
      <SingleMovieComp isLoading={loading} />
    </div>
  );
};

操作:

export function fetchMovieStart() {
  return {
    type: SingleMovieActionTypes.FETCH_MOVIE_START,
  };
}

export function fetchMovieSuccess(movie) {
  return {
    type: SingleMovieActionTypes.FETCH_MOVIE_SUCCESS,
    payload: movie,
  };
}

export function fetchMovieError(error) {
  return {
    type: SingleMovieActionTypes.FETCH_MOVIE_ERROR,
    payload: error,
  };
}

export const fetchMovieAsync = (movieId) => {
  return (dispatch) => {
    dispatch(fetchMovieStart());
    fetch(`URL`)
      .then((response) => response.json())
      .then((movie) => dispatch(fetchMovieSuccess(movie)))
      .catch((error) => dispatch(fetchMovieError(error.message)));
  };
};

减速器:

const INITIAL_STATE = {
  loading: false,
  movie: {},
};

const singleMovieReducer = (state = INITIAL_STATE, action) => {
  switch (action.type) {
    case SingleMovieActionTypes.FETCH_MOVIE_START: {
      return {
        ...state,
        movie: {},
        loading: true,
      };
    }
    case SingleMovieActionTypes.FETCH_MOVIE_SUCCESS: {
      return {
        ...state,
        movie: action.payload,
        loading: false,
      };
    }
    case SingleMovieActionTypes.FETCH_MOVIE_ERROR: {
      return {
        ...state,
        loading: false,
      };
    }
    default:
      return state;
  }
};

您可以尝试以下方法:

const ComponentWithSpinner = WithSpinner(SingleMovie);
//create single movie container
const SingleMovieContainer = (props) => {
  const { id } = useParams();
  const { fetchTheMovie } = props;
  //remove the useEffect from SingleMovie
  useEffect(() => {
    fetchTheMovie(id);
    //you need to add these dependencies
  }, [fetchTheMovie, id]);
  //Here you could try to use useSelector to get the movie
  //  and pass to SingleMovie but I think you already do
  //  that somewhere else
  //return component with spinner so SingleMovieContainer
  // will not unmount when you load movie
  return <ComponentWithSpinner {...props} />;
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(SingleMovieContainer);

问题是当您加载电影时 SingleMovie 被卸载,当加载为 false 时被加载,这导致加载被设置为 true(fetchMovie 被调度)所以它被再次卸载。