簡體   English   中英

如何從 API 響應中獲取初始 Redux state?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM