next-redux-wrapper travis-ci npm

Redux wrapper for Next.js

2 years after

Redux wrapper for Next.js

Usage

npm install next-redux-wrapper --save

Wrapper has to be attached your page components (located in /pages). For safety it is recommended to wrap all pages, no matter if they use Redux or not, so that you should not care about it anymore in all child components.

Here is the minimal setup (makeStore and reducer usually are located in other files):

import React, {Component} from "react";
import {createStore} from "redux";
import withRedux from "next-redux-wrapper";

const reducer = (state = {foo: ''}, action) => {
    switch (action.type) {
        case 'FOO':
            return {...state, foo: action.payload};
        default:
            return state
    }
};

const makeStore = (initialState) => {
    return createStore(reducer, initialState);
};

class Page extends Component {
    getInitialProps({store, isServer, pathname, query}) {
        store.dispatch({type: 'FOO', payload: 'foo'}); // component will be able to read from store's state when rendered
        return {custom: 'custom'}; // you can pass some custom props to component from here
    }
    render() {
        return (
            <div>
                <div>Prop from Redux {this.props.foo}</div>
                <div>Prop from getInitialProps {this.props.custom}</div>
            </div>
        )
    }
}

Page = withRedux(makeStore, (state) => ({foo: state.foo}))(Page);

export default Page;

How it works

No magic is involved, it auto-creates Redux store when getInitialProps is called by Next.js and then passes this store down to React Redux's Provider, which is used to wrap the original component, also automatically. On the client side it also takes care of using same store every time, whereas on server new store is created for each request.

The withRedux function accepts makeStore as first argument, all other arguments are internally passed to React Redux's connect() function for simplicity. The makeStore function will receive initial state as one argument and should return a new instance of redux store each time when called, no memoization needed here, it is automatically done inside the wrapper.

Async actions in getInitialProps

function someAsyncAction() {
    return {
        type: 'FOO',
        payload: new Promise((res) => { res('foo'); })
    }
}

function getInitialProps({store, isServer, pathname, query}) {

    // lets create an action using creator
    const action = someAsyncAction();

    // now the action has to be dispatched
    store.dispatch(action);

    // once the payload is available we can resume and render the app
    return action.payload.then((payload) => {
        // you can do something with payload now
        return {custom: 'custom'}; 
    });

}

Related Repositories

awesome-redux

awesome-redux

Awesome list of Redux examples and middlewares ...

react-router-redux

react-router-redux

Ruthlessly simple bindings to keep react-router and redux in sync ...

redux-auth

redux-auth

Complete token authentication system for react + redux that supports isomorphic ...

react-redux-jwt-auth-example

react-redux-jwt-auth-example

Sample project showing possible authentication flow using React, Redux, React-Ro ...

react-redux-provide

react-redux-provide

Bridges the gap between Redux and the declarative nature of GraphQL/Relay. Shar ...


Top Contributors

kirill-konshin brycejacobs remolueoend stevegeek iamsolankiamit robophil bmealhouse skv-headless ramiel devhyunjae clemencov icflorescu olistic montoias rwieruch sushant00 tobiastornros jason-ivy

Releases

-   2.0.0 zip tar
-   1.3.5 zip tar
-   1.3.4 zip tar
-   1.3.3 zip tar
-   1.3.2 zip tar
-   1.3.1 zip tar
-   1.3.0 zip tar
-   1.2.0 zip tar
-   1.1.3 zip tar
-   1.1.2 zip tar
-   1.1.1 zip tar
-   1.0.0 zip tar