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 '../../ponents/RunningLine'
import { fetchLatestNews } from '../../actions/wp_news'
class RunningLineContainer extends Component {
ponentDidMount() {
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!
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 '../../ponents/RunningLine'
import { fetchLatestNews } from '../../actions/wp_news'
class RunningLineContainer extends Component {
ponentDidMount() {
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!
Your action creator doesn't return Promise so it cannot be await
ed. 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,
})
})
}
}
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,
})
})
}
}