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 被调度)所以它被再次卸载。
我遇到了一个无限循环,它不断地从 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 被调度)所以它被再次卸载。