Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Next.js server waiting until action creator is fully done?

I'm using Next.js with Redux and I need to wait until action creator is fully done (including request to the external server) so data will be already in the initial rendering. I will try to explain this case in example.

I'm using HOC from example in docs and wrap page with it.

So, below you can see code example:

index.js in pages folder.

import withRedux from '../utils/withRedux'
import RunningLineContainer from '../src/containers/news/RunningLineContainer'

const IndexPage = () => <RunningLineContainer />

export default withRedux()(IndexPage)

RunningLineContainer.jsx

import React, { Component } from 'react'
import { connect } from 'react-redux'

import RunningLine from '../../components/RunningLine'
import { fetchLatestNews } from '../../actions/wp_news'

class RunningLineContainer extends Component {

    componentDidMount() {
        if (!this.props.lastestNews) {
            this.props.fetchLatestNews('&count=6')
        }
    }

    render() {
        const { latestNews, isLoading } = this.props
        return <RunningLine data={latestNews} isLoading={isLoading} />
    }
}

const mapStateToProps = ({ newsState }) => {
    const { latestNews, isLoading } = newsState
    return {
        latestNews,
        isLoading
    }
}

export default connect(mapStateToProps, { fetchLatestNews })(RunningLineContainer)

Currently, request is being made on the client side thus data from request is not rendered by the server and data content not being seen by search engines. My aim to make this data being responded on initial loading (rendered by the server).

Action creator code below:

export function fetchLatestNews(params) {
    return function (dispatch) {
        dispatch({ type: newsTypes.FETCH_WP_LATEST_NEWS_REQUEST })
        newsApi.fetchLatestNews(params)
            .then(response => {
                dispatch({
                    type: newsTypes.FETCH_WP_LATEST_NEWS_SUCCESS,
                    payload: response.data,
                })
            })
            .catch(error => {
                dispatch({
                    type: newsTypes.FETCH_WP_LATEST_NEWS_FAILURE,
                    payload: error,
                })
            })
    }
}

I've tried to use static method getInitialProps in index.js page like this:

import withRedux from '../utils/withRedux'
import RunningLineContainer from '../src/containers/news/RunningLineContainer'

const IndexPage = () => <RunningLineContainer />

IndexPage.getInitialProps = async ({ store }) => {
    await store.dispatch(fetchLatestNews())
}

export default withRedux()(IndexPage)

Unfortunately, it doesn't work for me.

How can I solve this task? Is there any workaround?

Thanks in advance!

like image 822
Denys Kotsur Avatar asked Nov 06 '25 19:11

Denys Kotsur


2 Answers

Your action creator doesn't return Promise so it cannot be awaited. Fix:

export function fetchLatestNews(params) {
    return function (dispatch) {
        dispatch({ type: newsTypes.FETCH_WP_LATEST_NEWS_REQUEST })

        // return statement
        return newsApi.fetchLatestNews(params)
            .then(response => {
                dispatch({
                    type: newsTypes.FETCH_WP_LATEST_NEWS_SUCCESS,
                    payload: response.data,
                })
            })
            .catch(error => {
                dispatch({
                    type: newsTypes.FETCH_WP_LATEST_NEWS_FAILURE,
                    payload: error,
                })
            })
    }
}
like image 139
Tomasz Mularczyk Avatar answered Nov 08 '25 13:11

Tomasz Mularczyk


Finally, I have resolved this task.

Actual solution is to make returning function in action creator asynchronous and add await to the API request.

So, I use static method as mentioned above like this:

import withRedux from '../utils/withRedux'
import RunningLineContainer from '../src/containers/news/RunningLineContainer'

const IndexPage = () => <RunningLineContainer />

IndexPage.getInitialProps = async ({ store }) => {
    await store.dispatch(fetchLatestNews())
}

export default withRedux()(IndexPage)  

My action creator looks like this:

export const fetchLatestNews = params => {
    return async dispatch => {
        dispatch({ type: newsTypes.FETCH_WP_LATEST_NEWS_REQUEST })
        await newsApi.fetchLatestNews(params)
            .then(response => {
                dispatch({
                    type: newsTypes.FETCH_WP_LATEST_NEWS_SUCCESS,
                    payload: response.data,
                })
            })
            .catch(error => {
                dispatch({
                    type: newsTypes.FETCH_WP_LATEST_NEWS_FAILURE,
                    payload: error,
                })
            })
    }
}
like image 37
Denys Kotsur Avatar answered Nov 08 '25 11:11

Denys Kotsur