Coder Social home page Coder Social logo

Comments (35)

jabacchetta avatar jabacchetta commented on June 16, 2024 7

In my case it turns out I wasn't returning the promise in my chain of dispatch functions. Working perfectly now!

For anyone else running into the same problem, here's an example:

Component — using async/await

static async getInitialProps({ store, query: { id } }) {
    await store.dispatch(loadQuoteIfNeeded(id))
    return { id }
 }

Actions — note that loadQuoteIfNeeded() has an implicit return and getQuote() is being returned

export const initiateLoadQuote = quoteId => (dispatch) => {
  dispatch(loadQuote(quoteId))

  return getQuote(quoteId)
    .then(({ data: quotes }) => {
      if (quotes === null) Router.push('/')
      dispatch(loadQuoteSuccess(quotes, quoteId))
    })
    .catch((err) => {
      dispatch(loadQuoteError(quoteId))
      logAjaxError('initiateLoadQuote', err)
    })
}

export const loadQuoteIfNeeded = quoteId => (dispatch, getState) => (
  shouldLoadQuote(getState(), quoteId) ? dispatch(initiateLoadQuote(quoteId)) : null
)

from next-redux-wrapper.

brunoqs avatar brunoqs commented on June 16, 2024 3

I have same issue, im using nextjs + redux toolkit I got the updated store on server, but i didnt get the store on client up to date like on server

static async  getInitialProps(ctx) {
   if (ctx.isServer) {
     if (ctx.store.getState().users.categories.length === 0) {
        const res = await ctx.store.dispatch(users.usersSlice.actions.getCategories());
        console.log(ctx.store.getState());
        // that console.log return the new state of redux server store
      }
    } else {
      console.log('ctx', ctx.store.getState());
    }
    return {}
  }

Action

getCategories: () => async dispatch => {
    dispatch(categoriesReset());
    try {
      dispatch(signupLoading());
      const res = await axios.get(`/api/v1/users/categories`);
      dispatch(categoriesSucces(res.data));
      return res.data;
    } catch (err) {
      dispatch(categoriesError(err.response.data));
      return err;
    }
  }

Store

import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
import rootReducers from "./rootReducers";
const initStoreSSR = {
  users: {
    data: {},
    status: 0,
    token: "",
    message: '',
    categories: []
  }
};
export const initStore = (preloadedState = {}) => {
  return configureStore({
    reducer: rootReducers,
    preloadedState: { ...preloadedState, ...initStoreSSR },
    middleware: [...getDefaultMiddleware()]
  });
};

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024 2

@brunoqs Looks like you’re overwriting your preloaded state with default state:

preloadedState: { ...preloadedState, ...initStoreSSR },

You need to change the order.

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024 1

I can't help with MobX. Regarding redux you MUST explicitly tell NextJS to await until all actions are dispatched: https://github.com/kirill-konshin/next-redux-wrapper#async-actions-in-getinitialprops

Pay close attention that you won't have any unhandled promises that were created inside the action.

from next-redux-wrapper.

muserref-sefer avatar muserref-sefer commented on June 16, 2024 1

@kirill-konshin Thank you for response. I'm using version 6. I handled the Hydrate action. This solved my problem.

import { HYDRATE } from 'next-redux-wrapper';

const authReducer = (state = {}, action) => {
  switch (action.type) {
    case HYDRATE:
      return {...state, ...action.payload.authReducer};
    case 'authenticate':
      return { ...state, token: action.payload };
    case 'deauthenticate':
      return { ...state, token: null };
    case 'getUser':
      return { ...state, user: action.payload };
    default:
      return state;
  }
};

export default authReducer

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024 1

@msefer just follow the example: https://github.com/kirill-konshin/next-redux-wrapper#usage

import {createStore} from 'redux';

// create a makeStore function
const makeStore = (context) => createStore(reducer);

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024 1

@jamal-rahimzadegan

function getInitialProps = async ({store}) => {
   await postRequest(store);
}

without await you will create a detached promise chain which will be executed in parallel and won't affect the resulting state that will be transferred to client before postRequest will finish. Also as a side note, you can't use store anywhere outside Next.js lifecycle hooks and/or components.

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024 1

@jamal-rahimzadegan create an action and use something like redux-thunk or redux-promise-middleware to dispatch it.

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024 1

@jamal-rahimzadegan https://github.com/kirill-konshin/next-redux-wrapper/blob/types-enchancements/packages/demo-saga/src/components/saga.tsx

from next-redux-wrapper.

patelmayankce avatar patelmayankce commented on June 16, 2024 1

https://github.com/vercel/next.js/tree/canary/examples/with-redux-wrapper follow this example.

https://github.com/vercel/next.js/blob/canary/examples/with-redux-wrapper/store/store.js

This configuration saves me.

from next-redux-wrapper.

jabacchetta avatar jabacchetta commented on June 16, 2024

For reference, here's what I have elsewhere:

quote.js

export default reduxPage(connect(mapStateToProps, connectedActions)(Quote))

redux.js

import withRedux from 'next-redux-wrapper'
import { applyMiddleware, createStore } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension/developmentOnly'
import thunk from 'redux-thunk'

import rootReducer from './modules'

const initStore = (initialState = {}) => {
  const middleware = composeWithDevTools(applyMiddleware(thunk))
  return createStore(rootReducer, initialState, middleware)
}

const reduxPage = page => withRedux(initStore)(page)

export default reduxPage

rootReducer.js

import { combineReducers } from 'redux'

import appReducer from '../modules/app'
import dataReducer from '../modules/data'
import uiReducer from '../modules/ui'

const rootReducer = combineReducers({
  app: appReducer,
  data: dataReducer,
  ui: uiReducer,
})

export default rootReducer

from next-redux-wrapper.

jchbh-duplicate avatar jchbh-duplicate commented on June 16, 2024

I meet similar problem, Reducer has already update in server. But front-page do not received any update.
I use with saga to do very basic async loading.

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024

Can you look at the snapshot state delivered from the server? If it's correct but UI keeps loading things — you need to add conditions in getInitialProps to load only needed things. If server state is incorrect/not full — you probably missed async loading of something.

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024

This is a very wide-spread issue... unfortunately library has nothing to do with it. But, if you use Bluebird, it will tell you that there is a lost promise.

from next-redux-wrapper.

phumaster avatar phumaster commented on June 16, 2024

Same issue :(

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024

@phumaster can you describe your issue? The one in the topic was a lost promise, do you have it as well?

from next-redux-wrapper.

jabacchetta avatar jabacchetta commented on June 16, 2024

@phumaster Have you referred to my solution to the problem to see if it solved it for you?

from next-redux-wrapper.

phumaster avatar phumaster commented on June 16, 2024

Hi, thank for the response. When I dispatch an action. The NextJS render but not wait for action resolve. Then, I switch to use MobX. It's well. Now, MobX render object from the server like pic 1
screen shot 2018-04-03 at 3 21 56 pm
And client side object is not plain javascript.
screen shot 2018-04-03 at 3 55 45 pm

Should I create issue? Sorry for my english.

from next-redux-wrapper.

phumaster avatar phumaster commented on June 16, 2024

@kirill-konshin Thank you. I think, My problem with Redux is created new a promise when action dispatch. I will try it again.

from next-redux-wrapper.

rehan-sattar avatar rehan-sattar commented on June 16, 2024

I'm using redux saga and facing the same issue as @jabacchetta was facing. Everything is perfect till my reducer but my store's state is note updated. Anyone ?

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024

Can you provide the repo to reproduce?

from next-redux-wrapper.

rehan-sattar avatar rehan-sattar commented on June 16, 2024

@kirill-konshin I solved it with componentDidMount in _app.js. As it runs on the client side and will work perfectly.

from next-redux-wrapper.

brunoqs avatar brunoqs commented on June 16, 2024

@kirill-konshin thx a lot dude, u saved my friday

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024

@brunoqs you're most welcome.

from next-redux-wrapper.

muserref-sefer avatar muserref-sefer commented on June 16, 2024

I've same issue. Store not updating.

Store.js

import thunk from 'redux-thunk';
import rootReducer from "../redux/reducers/rootReducer";
import {createStore, applyMiddleware, combineReducers, compose} from 'redux';

const composeEnhancer = typeof window == 'object' &&
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ &&
process.env.NODE_ENV !== "production" ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})  : compose;

const store = createStore(rootReducer, composeEnhancer(applyMiddleware(thunk)));

export default store;

_app.js

import App from 'next/app'
import React from "react";
import store from '../redux/store';
import { Provider } from 'react-redux';
import withRedux from "next-redux-wrapper";
import { appWithTranslation } from '../i18n';
import 'bootstrap/dist/css/bootstrap.min.css';
import Layout from '../components/Layout/Layout';

function AppPage({ Component, pageProps }) {
  return (
    <>
      <Provider store={store}>
        <Layout>
          <Component {...pageProps} />
        </Layout>
      </Provider>
    </>
  )
}

AppPage.getInitialProps = async (appContext) => {
  const appProps = await App.getInitialProps(appContext);
  return { ...appProps }
};

// makeStore function that returns a new store for every request
const makeStore = () => store;

// withRedux wrapper that passes the store to the App Component
export default withRedux(makeStore)(appWithTranslation(AppPage));

index.js

import api from "../api";
import Head from 'next/head'
import Home from '../components/Home/Index';
import { parseCookies } from '../lib/parseCookies';
import { authenticate } from "../redux/actions/authActions";

function HomePage({ user }) {
  return (
    <>
      <Head>
        <title>Anasayfa</title>
      </Head>

      <Home />
    </>
  )
}

HomePage.getInitialProps = async (ctx) => {
  const { store } = ctx;
  const cookies = parseCookies(ctx.req);
  const data = "Bearer " + cookies.token;
  const response = await api.getUser(data);

  store.dispatch({ type: "authenticate", payload: "testToken" });

  console.log(store.getState().authReducer.token);

  return { user: response ? response.data : null };
};

export default HomePage

rootReducer.js

import { combineReducers } from "redux";
import authReducer from './authReducer';

const rootReducer = combineReducers({
  authReducer
});

export default rootReducer

authReducer.js

const authReducer = (state = {}, action) => {
  switch (action.type) {
    case 'authenticate':
      return { ...state, token: action.payload };
    case 'deauthenticate':
      return { ...state, token: null };
    case 'getUser':
      return { ...state, user: action.payload };
    default:
      return state;
  }
};

export default authReducer

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024

@msefer if you are using version 6 you must handle the HYDRATE action.

If you are on version 5 it looks like you always use one store instead of a createStore function that accepts initialState.

Your usage is something really odd. It does not follow the guidelines.

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024

@msefer great! But still you should not export default store. You need to create it dynamically...

// makeStore function that returns a new store for every request
const makeStore = () => store;

Your code does exactly the opposite from what comment suggests.

Also I suggest to start using createWrapper instead of import withRedux from "next-redux-wrapper";. This is deprecated.

from next-redux-wrapper.

muserref-sefer avatar muserref-sefer commented on June 16, 2024

@kirill-konshin How can I create the store dynamically?

I'm start using createWrapper instead of withRedux. In this way:

export default createWrapper(makeStore)(appWithTranslation(AppPage));

from next-redux-wrapper.

jamal-rahimzadegan avatar jamal-rahimzadegan commented on June 16, 2024

I have a similar problem, I can update store form getInitialProps and inside the components, but not in an independent function

export function postRequest() {
  return new Promise((resolve, reject) => {
    let store=STORE()
    **store.dispatch({ type: 'SET_TOKEN', payload: { token:'passed token' } });**
    axios
      .post(URL, params || {}, headers(token))
      .then((response) => {
        resolve(response);
      })
      .catch((error) => {
      })
      .finally(() => {});
  })

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024

@jamal-rahimzadegan do you await for this function in the executor?

from next-redux-wrapper.

jamal-rahimzadegan avatar jamal-rahimzadegan commented on June 16, 2024

@jamal-rahimzadegan do you await for this function in the executor?

what do you mean?
its a function outside of component

from next-redux-wrapper.

jamal-rahimzadegan avatar jamal-rahimzadegan commented on June 16, 2024

@kirill-konshin
thank you for your fast response.
I want to create a reusable Axios request function that dispatches
how could I achieve this?

from next-redux-wrapper.

jamal-rahimzadegan avatar jamal-rahimzadegan commented on June 16, 2024

@kirill-konshin
I'm using redux-saga could you give me some link or any advice for this?

from next-redux-wrapper.

vitalii4reva avatar vitalii4reva commented on June 16, 2024

how to use HYDRATE with redux-toolkit createReducer?

const userReducer = createReducer(initialState, {
  [HYDRATE]: (state, action) => {
    state = { ...state, ...action.payload.userReducer };
  },

Is it wrong?

from next-redux-wrapper.

kirill-konshin avatar kirill-konshin commented on June 16, 2024

how to use HYDRATE with redux-toolkit createReducer?

const userReducer = createReducer(initialState, {
  [HYDRATE]: (state, action) => {
    state = { ...state, ...action.payload.userReducer };
  },

Is it wrong?

https://github.com/kirill-konshin/next-redux-wrapper/blob/types-enchancements/packages/demo-redux-toolkit/store.tsx#L18

from next-redux-wrapper.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.