5

Next.js v12.0

next-redux-wrapper.

Whenever I navigate away from the page using the appropriate next/link element and then back again (using another link el) the state is reset to the initial value and so another fetch is executed. What is strange about this is that I have another 'transaction' slice setup in an identical manner except it holds an array of transaction objects and that one is working just fine (navigate away and back and the data is not re-fetched as it persisted in store) code is below any suggestions would be greatly appreciated.

store.js

import { HYDRATE, createWrapper } from "next-redux-wrapper";
import thunkMiddleware from "redux-thunk";
import address from "./address/reducer";
import transactions from "./transaction/reducer";

const bindMiddleware = (middleware) => {
  if (process.env.NODE_ENV !== "production") {
    const { composeWithDevTools } = require("redux-devtools-extension");
    return composeWithDevTools(applyMiddleware(...middleware));
  }
  return applyMiddleware(...middleware);
};

const combinedReducer = combineReducers({
  transactions,
  address,
});

const rootReducer = (state, action) => {
  if (action.type === HYDRATE) {
    const nextState = {
      ...state, // use previous state
      ...action.payload, // apply delta from hydration
    };
    
    if (state.address.id){
      nextState.address = state.address;
    }
    return nextState;
  } else {
    return combinedReducer(state, action);
  }
};


const initStore = () => {
  return createStore(rootReducer, bindMiddleware([thunkMiddleware]));
};
export const wrapper = createWrapper(initStore);

address/reducer.js


const addressInitialState = {
  id: null,
  timestamp: null,
  address: null,
  balance: null,
  received: null,
  sent: null,
  groupid: null,
  last_txs: []
};

export default function reducer(state = addressInitialState, action) {
  switch (action.type) {
    case addressActionTypes.GET_WALLET_DETAILS:
      return {id: action.payload.address, ...action.payload};
    default:
      return state;
  }
}

address/action.js

export const addressActionTypes = {
  GET_WALLET_DETAILS: "GET_WALLET_DETAILS",
};

export const getWalletDetails = (address) => {
  return async (dispatch) => {
    const fetchData = async () => {
      const response = await fetch(
        `https:someapi.com/api/getaddress/?address=${address}`
      );
      if (!response.ok) {
        throw new Error("Could not fetch address data!");
      }

      const data = await response.json();
      console.log('req sent');
      return data;
    };
    try {
      const addressData = await fetchData();
      dispatch({
        type: addressActionTypes.GET_WALLET_DETAILS,
        payload: addressData,
      });
    } catch (err) {
      console.log(err);
    }
  };
};

pages/[address].js

import { Fragment } from "react";
import Head from "next/head";
import AddressDetails from "../../../components/crypto/rvn/AddressDetails";
import AddressTransactions from "../../../components/crypto/rvn/AddressTransactions";
import { connect } from "react-redux";
import { getWalletDetails } from "../../../store/address/action";
import { wrapper } from "../../../store/store";

function Address(props) {
  return (
    <Fragment>
      <Head>
        <title>RVN</title>
        <meta name="description" content="RVN Address" />
      </Head>
      <AddressDetails address={props.addressDetails}></AddressDetails>
      <AddressTransactions
        transactions={props.addressDetails["last_txs"]}
        address={props.addressDetails.address}
      ></AddressTransactions>
    </Fragment>
  );
}

export const getServerSideProps = wrapper.getServerSideProps(
  (store) => async (context) => {
    const state = store.getState();
    if(state.address.id === null) {
      await store.dispatch(getWalletDetails(context.params.address));
    }
    else{
      return{
        props: {
          addressDetails: state.address,
        }
      }
    }
  }
);


const mapStateToProps = (state) => ({
  addressDetails: state.address,
});
export default connect(mapStateToProps, null)(Address);
James Gagne
  • 91
  • 1
  • 5
  • I figured out that the state is persisting in this case however, it is only being set in the client side state as opposed to the server side state where i need it – James Gagne Oct 31 '21 at 04:00

1 Answers1

4

Solved this by converting this

const initStore = () => {
  return createStore(rootReducer, bindMiddleware([thunkMiddleware]));
};

in store.js which direclty from https://github.com/vercel/next.js/tree/canary/examples/with-redux-thunk

to this

const store = createStore(rootReducer, bindMiddleware([thunkMiddleware]));

const initStore = () => {
  return store
};

so it does not reinitialize the store every time the wrapper is used

this is more in line with the documentation at https://github.com/kirill-konshin/next-redux-wrapper

James Gagne
  • 91
  • 1
  • 5