I am new to next-redux-wrapper and trying to use it to persist the state across pages.
On the home page, I have login action. When login succeeds, I am adding a session.loggedIn : true to redux store.
When I transition to the next page (getServerSideProps), the HYDRATE action is being called, but the action.payload is empty. When this empty object is merged with the previous state, all the previous states is getting lost.
Here is the snapshot of the state merge redux-logger:
My code in first page with getInitial Props:
//Index.getInitialProps = async(/* ctx */) => {
Index.getInitialProps = wrapper.getInitialPageProps( store => async ({pathname, req, res}) => {
try {
let promises = []
promises.push(fetch(URLMap("categoriesAPI")).then(res => res.json()))
const pageNum=1, itemsPerPage=10
let collectionsURL = URLMap('myCollectionAPI')
collectionsURL = `${collectionsURL}?pageNum=${pageNum}&itemsPerPage=${itemsPerPage}`
promises.push(fetch(collectionsURL).then(res => res.json()))
let results = await Promise.all(promises)
//console.log("Result of my collections: ",results[1])
return {categories:results[0].categories, products:results[1].products}
} catch (e) {
console.error("errr while fetching data in 'getInitialProps'", e)
//TODO: Implement a google like notification indicating network failure.
return {}
}
})
The transitioned (new page) has this code for getServerSideProps:
export default connect(state => state)(ShopProductPage)
//export async function getServerSideProps({query}) {
export const getServerSideProps = wrapper.getServerSideProps(store => async({query}) => {
console.log('Inside server side props');
let shopId = query.shopId
let productId = query.productId;
console.log("shop id:", shopId)
console.log("product id:", productId)
let promises = []
promises.push(getShopInfo(shopId));
promises.push(getProductInfo(productId));
try {
let allPromises = Promise.all(promises)
let results = await allPromises;
return {props: {
id: shopId,
shopInfo: results[0],
productInfo :results[1]
}}
} catch(e) {
console.error("Failure:", e)
return { props: {}}
}
})
I can see that every time I navigate to a new page, the hydrate payload is empty and overriding the previous state. Am I missing anything here?
EDIT
My reducer code is as follows: I realized that there is not much of a state on the server side, and if I merge it with client's state, it will clean sweep. So, I decided to return the state unmodified (without merge) in he hydrate method. Now, it works fine for my use case.
I have another issue wherein If I reload the page, or navigate to new page through browser's addressbar, it will be a new load and no state is available. It looks like I have use Redux Persist to solve this 2nd problem.
import {applyMiddleware, createStore} from 'redux';
import {createWrapper, HYDRATE} from 'next-redux-wrapper';
import thunk from "redux-thunk"
import logger from 'redux-logger'
let store
const initialState = {
//TODO: Add initial state of our app here.
//showLogin: false,
loginProcessState: 0, // 0:false (don't show), 1:showLoginDialog, 2:login submit begin, 3: login submit failed, 4:showOTPDialog,
contactInfoDisplay: false, // false:don't show; true: show
contactEditDisplay: false,
session: { loggedIn : false
/*
// If logged in, it will have these values also (sample)
name: "Ravindranath M",
mobile: "xxxxxxx982",
email: "someone@somewhere.com",
pincode: "560097"
*/
},
cart: {total: 0, products : []}, // product structure {_id:'', qty:''}
contactInfoDisplay: 0 //0:no display, 1:display, 2:edit
}
const reducer = (state=initialState, action) => {
switch (action.type) {
case HYDRATE: // important case for persisting state between client and server!
//return {...state, ...action.payload}
return {...state }
case 'SET_CATEGORIES':
return {
...state,
categories: action.categories
}
case 'SHOW_LOGIN_DLG':
console.log("Reducer executing 'SHOW_LOGIN_DLG' action...")
return { ...state, loginProcessState: 1 } // show login dialog