Mehdi Faraji
Mehdi Faraji

Reputation: 3806

How to configure redux with next js?

I configured redux this way and it works.

This is the _app.js file reconfigured :

import App from 'next/app';
import { Provider } from 'react-redux';
import withRedux from 'next-redux-wrapper';
import store from '../redux/store';
import React from 'react';

class MyApp extends App {
    static async getInitialProps({ Component, ctx }) {
        const appProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {};

        console.log(appProps);

        return {
            appProps: appProps
        };
    }
    render() {
        const { Component, appProps } = this.props;
        return (
            <Provider store={store}>
                <Component {...appProps} />
            </Provider>
        );
    }
}

const makeStore = () => store;

export default withRedux(makeStore)(MyApp);

This is the index.js file which I've connected to redux :

import { connect } from 'react-redux';
import { callAction } from '../redux/actions/main';

const Index = (props) => {
    console.log(props);
    return (
        <div>
            Index js state <button onClick={() => props.callAction()}>Call action</button>
        </div>
    );
};

const mapStateProps = (state) => ({
    name: state.main.name
});

const mapDispatchProps = {
    callAction: callAction
};

export default connect(mapStateProps, mapDispatchProps)(Index);

This is the rootReducer file which gets only one reducer named main :

import { main } from './main';
import { combineReducers } from 'redux';

export const rootReducer = combineReducers({
    main: main
});

And this is the store.js file :

import { createStore } from 'redux';
import { rootReducer } from './reducers/rootReducer';

const store = createStore(rootReducer);

export default store;

It all works fine but it throws a warning in the console which says : /!\ You are using legacy implementaion. Please update your code: use createWrapper() and wrapper.withRedux().

What changes to which files I need to make to fix the legacy implementation warning?

Upvotes: 1

Views: 6313

Answers (2)

I would like to leave this answer, it worked for me in TS

================== _app.tsx ================== 
import type { AppProps } from 'next/app'
import { Provider } from 'react-redux';
import { createWrapper } from 'next-redux-wrapper';
import { store } from '../redux/store';

function MyApp({ Component, pageProps }: AppProps & { Component: { layout: any }}) {
  const Layout = Component.layout || (({ children }) => <>{children}</>);
  return (
    <Provider store={store}>
      <Layout>
        <Component {...pageProps} />
      </Layout>
    </Provider>
  );
}

MyApp.getInitialProps = async ({ Component, router, ctx }) => {
  const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {};
  return { pageProps };
}

const makeStore = () => store;
const wrapper = createWrapper(makeStore);

export default wrapper.withRedux(MyApp);
================== store.tsx ================== 
import { applyMiddleware, createStore } from 'redux';
import thunkMiddleware from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension';

import { rootReducer } from '../reducers';

export const store = createStore(
  rootReducer,
  composeWithDevTools(applyMiddleware(thunkMiddleware)),
);

export type AppDispatch = typeof store.dispatch;
================== reducers.tsx ================== 
import * as redux from 'redux';
import { ThunkDispatch } from 'redux-thunk';
import { Action } from 'typesafe-actions';

import user from './user';

export const rootReducer = redux.combineReducers({
  user,
});

export type AppThunkDispatch = ThunkDispatch<RootState, void, Action>;
export type RootState = ReturnType<typeof rootReducer>;

================== onereducer.tsx ================== 
import { HYDRATE } from "next-redux-wrapper";
import { Reducer } from 'redux';
import { ActionType } from 'typesafe-actions';
import { USER_ACTIONS } from '../../actions/types';
import { IUserData } from './types';

const userState: IUserData = {
  _id: '',
  email: '',
  password: '',
  role: '',
};

const userReducer: Reducer<IUserData, ActionType<any>> = (
  state = userState,
  action,
) => {
  switch (action.type) {
    case HYDRATE:
      return { ...state, ...action.payload.userData };
    case USER_ACTIONS.SET_USER_DATA:
      return { ...state, ...action.payload.userData };
    default:
      return { ...state };
  }
};

export default userReducer;

PD: Still a work in progress but works!

Upvotes: 1

Mehdi Faraji
Mehdi Faraji

Reputation: 3806

I solved the warning by changing the way I get redux states and actions in index.js and the way passing them in _app.js files by using the createWrapper and withRedux :

_app.js

import App from 'next/app';
import store from '../redux/store';
import { Provider } from 'react-redux';
import { createWrapper } from 'next-redux-wrapper';

class MyApp extends App {
    render() {
        const { Component, pageProps } = this.props;
        return (
            <Provider store={store}>
                <Component {...pageProps} />
            </Provider>
        );
    }
}
const makeStore = () => store;
const wrapper = createWrapper(makeStore);

export default wrapper.withRedux(MyApp);

index.js

import { callAction } from '../redux/action';
import { connect } from 'react-redux';

const Index = (props) => {
    return (
        <div>
            hey {props.name}
            <br />
            <button onClick={() => props.callAction()}>Call action</button>
        </div>
    );
};

const mapState = (state) => {
    return {
        name: state.name
    };
};

const mapDis = (dispatch) => {
    return {
        callAction: () => dispatch(callAction())
    };
};

export default connect(mapState, mapDis)(Index);

Upvotes: 1

Related Questions