Jonas
Jonas

Reputation: 7875

Redux Store populates in getInitialProps but is empty on client

I'm using the Redux Thunk example template. When I dispatch an action in getInitialProps, that populates my store, the data is loaded but after the page is rendered, the store is still empty.

static async getInitialProps({ reduxStore }) {
  await reduxStore.dispatch(fetchCategories())
  const categories = reduxStore.getState().programm.categories;
  console.log('STATE!!!', categories)

  return { categories }
}

The categories will load correctly but when I inspect my store, the categories state is empty.

Here is my store:

import db from '../../api/db'

// TYPES
export const actionTypes = {
    FETCH_PROGRAMMS: 'FETCH_PROGRAMMS',
    FETCH_CATEGORIES: 'FETCH_CATEGORIES'
}

// ACTIONS
export const fetchCategories = () => async dispatch => {

    const categories = await db.fetchCategories();
    console.log('loaded Cate', categories)

    return dispatch({
        type: actionTypes.FETCH_CATEGORIES,
        payload: categories
    })

}


// REDUCERS
const initialState = {
    programms: [],
    categories: []
}

export const programmReducers = (state = initialState, action) => {
    switch (action.type) {
        case actionTypes.FETCH_PROGRAMMS:
            return Object.assign({}, state, {
                programms: action.payload
            })
        case actionTypes.FETCH_CATEGORIES:
            console.log('Payload!', action);
            return Object.assign({}, state, {
                categories: action.payload
            })
        default:
            return state
    }
}

How can I make the redux state loaded on the server (in getInitialProps) be carried over to the client?

Upvotes: 2

Views: 1083

Answers (2)

Jonas
Jonas

Reputation: 7875

After hours of searching for solution it seems like I found my problem. It seems like I need to pass an initialState when creating the store. So instead of this:

export function initializeStore() {
    return createStore(
        rootReducers,
        composeWithDevTools(applyMiddleware(...middleware))
    )
}

I'm doing this and it works now

const exampleInitialState = {}

export function initializeStore(initialState = exampleInitialState) {
    return createStore(
        rootReducers,
        initialState,
        composeWithDevTools(applyMiddleware(...middleware))
    )
}

Upvotes: 1

Pho Huynh
Pho Huynh

Reputation: 1577

If you do this:

return { categories }

in getInitialProps, categories should be available in component's props in client side.

It should be available in Redux as well, this could cause the problem:

return Object.assign({}, state, {
  categories: action.payload
})

Take a look at this Object.assign, the function only takes 2 parameters.

My normal way of doing this:

return {
  ...state,
  categories: action.payload,
};

Upvotes: 0

Related Questions