Next.js: Question: Next.js 5.1.0 with redux in SSR - How to get state from store in SSR?

Created on 17 May 2018  路  5Comments  路  Source: vercel/next.js

It's okay when I dispatch action in client side, all work as normal react redux app.

But my question would be like do I need to use redux in SSR or just simply fetch api and then base on api response to create dynamic web content in SSR - this do not need redux at all.
I am kinda confuse.

I still can get the dispatch and reducer work as normal in SSR.

But I don鈥檛 know how to grab the state out.

If can get state from store (when I can't do it now and struggling how to do it) how to do I pass it from server side to client side?

I am using this https://github.com/zeit/next.js/tree/5.1.0/examples/with-redux as example to implement my app right now.

Please correct me if I have anything misunderstanding.

Thanks for the helping hand!

Environment:
Next.js 5.1.0

Most helpful comment

@thanhvk
Action:

import { GET_LATEST_FIVE_ARTICLES } from './types';
import api from '../config/api';

const getLatestFiveArticles = (endpoint, language) => {
    return async (dispatch) => {
        await fetch(endpoint + api.latestFive + `?language=${language}`)
        .then((response) => response.json())
        .then((data) => {
            dispatch({
                type: GET_LATEST_FIVE_ARTICLES,
                articles: data
            });
        })
        .catch((error) => console.log(error));
    }
}

export { getLatestFiveArticles };

Reducer:

import { GET_LATEST_FIVE_ARTICLES } from '../actions/types';

const INITIAL_STATE = {
    articles: []
};

export default (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case GET_LATEST_FIVE_ARTICLES:
            return {
                articles: action.articles
            };
        default:
            return state;
    }
}

Page:

static async getInitialProps({ req, pathname, t, i18n, store }) {
        let endpoint;
        let language;

        if (req) {
            endpoint = process.env.API_ENDPOINT;
            language = req.language;
        }
        else {
            endpoint = '/';
            language = I18n.language;
        }

        await store.dispatch(getLatestFiveArticles(endpoint, language));

        return { pathname, t, i18n };
    }

for your reference

All 5 comments

SSR is only for rendering the initial state, after the first render we have a normal client side redux app.

You can see in the store there's an action called startClock() which dispatches an action every one second, that only happens after client render.

For state: look at /components/Page.js there's a redux connect function that spreads the state of the Store into props of the react components. Sometimes people namespace any higher order connect components under the folder such as /containers so it's clearer.

I solved this with async wait pattern. I forgot about JavaScript async patten need to wait until the XHR call to finish. Otherwise, no data can be get at that point.

Hi @joelamltc ,

You can show details your solution. I've same issue with you. I use a function dispatch in getInitialProps to dispatch an action get data from API and I've a reducer to update state but it seem alway get initialState, not nextState

@thanhvk
Action:

import { GET_LATEST_FIVE_ARTICLES } from './types';
import api from '../config/api';

const getLatestFiveArticles = (endpoint, language) => {
    return async (dispatch) => {
        await fetch(endpoint + api.latestFive + `?language=${language}`)
        .then((response) => response.json())
        .then((data) => {
            dispatch({
                type: GET_LATEST_FIVE_ARTICLES,
                articles: data
            });
        })
        .catch((error) => console.log(error));
    }
}

export { getLatestFiveArticles };

Reducer:

import { GET_LATEST_FIVE_ARTICLES } from '../actions/types';

const INITIAL_STATE = {
    articles: []
};

export default (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case GET_LATEST_FIVE_ARTICLES:
            return {
                articles: action.articles
            };
        default:
            return state;
    }
}

Page:

static async getInitialProps({ req, pathname, t, i18n, store }) {
        let endpoint;
        let language;

        if (req) {
            endpoint = process.env.API_ENDPOINT;
            language = req.language;
        }
        else {
            endpoint = '/';
            language = I18n.language;
        }

        await store.dispatch(getLatestFiveArticles(endpoint, language));

        return { pathname, t, i18n };
    }

for your reference

I'll close this as it's solved.

Was this page helpful?
0 / 5 - 0 ratings