[英]How do I fetch the initial Redux state from an API response?
看到了幾個關於此的問題,但有許多不清楚和不同的答案。
我在我的組件的第一次加載中呈現項目列表,目前我正在觸發這個獲取,如下所示:
fetchMovies = () => {
console.log('component page:', this.props.movie.page);
this.props.getMoviesIfNeeded(this.props.movie.page);
};
handleScroll = throttle(() => {
let d = document.body;
let scrollTop = window.scrollY;
let windowHeight = window.innerHeight || document.documentElement.clientHeight;
let height = d.offsetHeight - windowHeight;
let scrollPercentage = (scrollTop / height);
// if the scroll is more than 90% from the top, load more content.
if (scrollPercentage > 0.90) {
// this.fetchMovies();
if (!this.props.movie.isFetching) {
this.props.increasePage();
}
}
}, 1000);
componentDidMount() {
if (this.props.movie.page === 1) {
this.fetchMovies();
}
window.addEventListener('scroll', this.handleScroll);
}
我的問題是它自然會在每個 Route 導航到組件時執行。 (當前:列表頁 => 詳細頁 => 列表頁)並且每次都重新執行。 我想刪除對 fetchMovies 的調用並將其移至傳入的 initialState:\
export default function configureStore() {
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
return createStore(
reducers,
+ initialState, // there
composeEnhancers(applyMiddleware(thunk))
);
}
如文檔中所述: https://redux.js.org/recipes/configuring-your-store#the-solution-configurestore 。 在這種情況下,HTTP 請求應該在哪里? 目前,獲取是在我的操作文件中完成的:
export let getMovies = (page = 1) => async dispatch => {
let err, response;
dispatch(requestMovies(page));
[err, response] = await to(axios.get(`${apiUrls.base}/${apiUrls.theaters}`, {
params: {
page,
api_key: '36081eca9a2ced64d616c59681881626',
}
}));
console.log('request done with page:', page);
if (err) return dispatch(throwError(err));
debugger;
return dispatch(receiveMovies(response.data));// somewhere here I want to trigger another action that increases the page...?
};
我的應用程序不是 SSR 應用程序 (NextJS),而是簡單的 React。
編輯這些是其他動作和減速器
// actions
function shouldFetchMovies(state, page) {
if (!state.movie.movies.length) {
return true;
} else if (state.movie.isFetching) {
return false;
} else {
return state.movie.movies;
}
}
export function getMoviesIfNeeded(page) {
return (dispatch, getState) => {
if (shouldFetchMovies(getState(), page)) {
return dispatch(getMovies(page));
}
}
}
// reducers
const defaultState = {
movies: [],
total: 0,
page: 1,
isFetching: false,
};
export default (state = defaultState, action) => {
switch (action.type) {
case 'INCREASED_PAGE':
return {
...state,
page: state.page + 1,
};
case 'REQUESTED_MOVIES':
return {
...state,
isFetching: true,
};
case 'RECEIVED_MOVIES':
return {
...state,
movies: [...state.movies, ...action.response.results],
// total: action.response.total_results,
isFetching: false,
};
default:
return state;
}
}
initialState
- 是 object。 這不是您應該調用任何獲取操作的地方。 副作用最好的地方是componentDidMount
lifecylce 方法。 所以你的調用實現是正確的。
如果你要改變 redux state 你應該使用減速器。 您必須為您在receiveMovies
操作創建器中使用的操作創建減速器,這將更新應用程序 state。 在那里,您可以從您的響應中獲取數據並更新您需要的任何 state 值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.