How do I fetch the initial Redux state from an API response?

馋奶兔 提交于 2020-05-17 06:06:02

问题


Seen several questions about this but with many unclear and different answers.

I am rendering a list of items in the very first load of my component, and currently I'm triggering this fetch like so:

  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);
  }

my problem with this is that naturally it is executed at every Route navigation to the component. (currently: list page => detail page => list page) and it is re-executed each time. I would like to remove this call to fetchMovies and move it to the initialState passed in:\

export default function configureStore() {
  const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
  return createStore(
    reducers,
  + initialState, // there
    composeEnhancers(applyMiddleware(thunk))
  );
}

as described in the documentation: https://redux.js.org/recipes/configuring-your-store#the-solution-configurestore . In this case, where should the HTTP Request live? Currently, the fetching is done in my actions file:

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...?
};

My application is not a SSR app (NextJS) but plain simple React.

edit these are the other actions and reducers

// 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;
  }
}

回答1:


initialState - is a object. It's not the place you should call any fetch operations. The best place for side-effects is componentDidMount lifecylce method. So your implementation for callling is correct.

If you are going to change redux state you should use reducers. You have to create reducer for the action you use in receiveMovies action creator which will update app state. There you can get data from your response and update any state values you need.



来源:https://stackoverflow.com/questions/61777920/how-do-i-fetch-the-initial-redux-state-from-an-api-response

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!