简体   繁体   中英

Using react redux with next.js

I try to use Redux with next.js starter project and I installed next-redux-wrapper on the project but I'm not sure where is the root file in this project.

I try to follow the tutorial shown on the next-redux-wrapper but had no success. Nothing change.

Please help me with how to add Redux to the project.

Regards.

Next.js uses the App component to initialize pages. You can override it and control the page initialization.

Although this demo is for next.js it should work for nextjs-starter.

install next-redux-wrapper:

npm install --save next-redux-wrapper

Add _app.js file to ./pages directory:

// pages/_app.js
import React from "react";
import {createStore} from "redux";
import {Provider} from "react-redux";
import App, {Container} from "next/app";
import withRedux from "next-redux-wrapper";

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

/**
* @param {object} initialState
* @param {boolean} options.isServer indicates whether it is a server side or client side
* @param {Request} options.req NodeJS Request object (not set when client applies initialState from server)
* @param {Request} options.res NodeJS Request object (not set when client applies initialState from server)
* @param {boolean} options.debug User-defined debug mode param
* @param {string} options.storeKey This key will be used to preserve store in global namespace for safe HMR 
*/
const makeStore = (initialState, options) => {
    return createStore(reducer, initialState);
};

class MyApp extends App {

    static async getInitialProps({Component, ctx}) {

        // we can dispatch from here too
        ctx.store.dispatch({type: 'FOO', payload: 'foo'});

        const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {};

        return {pageProps};

    }

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

}

export default withRedux(makeStore)(MyApp);

And then, actual page components can be simply connected: This demo how to connect index.js in pages.

import Link from "next/link";
import React from "react";
import {
  Container,
  Row,
  Col,
  Button,
  Jumbotron,
  ListGroup,
  ListGroupItem
} from "reactstrap";
import Page from "../components/page";
import Layout from "../components/layout";

import { connect } from "react-redux";

class Default extends Page {
  static 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 (
      <Layout>content...</Layout>
    );
  }
}

export default connect()(Default);

Refer to the documentation for more information: next-redux-wrapper

First i created simple next.js app with "npx create-next-app"

Then I created general redux setup in a folder called "store".

This is the folder structure在此处输入图像描述

And in pages i have created an _app.js. Code inside it is like this- 在此处输入图像描述

Please let me know if anyone needs any help with setup...

this question needs update:

"next": "12.1.4",
"next-redux-wrapper": "^7.0.5",
"redux-devtools-extension": "^2.13.9",
"redux-thunk": "^2.4.1"

Create Store

import { createStore, applyMiddleware } from "redux";
import { HYDRATE, createWrapper } from "next-redux-wrapper";
import reducers from "./reducers/reducers";

import thunkMiddleware from "redux-thunk";

// middleware is an array
const bindMiddleware = (middleware) => {
  if (process.env.NODE_ENV !== "production") {
    const { composeWithDevTools } = require("redux-devtools-extension");
    return composeWithDevTools(applyMiddleware(...middleware));
  }
  return applyMiddleware(...middleware);
};
// this is main reducer to handle the hydration
const reducer = (state, action) => {
  // hydration is a process of filling an object with some data
  // this is called when server side request happens
  if (action.type === HYDRATE) {
    const nextState = {
      ...state,
      ...action.payload,
    };
    return nextState;
  } else {
    // whenever we deal with static rendering or client side rendering, this will be the case
    // reducers is the combinedReducers
    return reducers(state, action);
  }
};

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

export const wrapper = createWrapper(initStore);

_app.js

import { wrapper } from "../redux/store";

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

export default wrapper.withRedux(MyApp);

Using it with getServerSideProps

// sample action
import { getRooms } from "../redux/actions/roomActions";
import { wrapper } from "../redux/store";

export const getServerSideProps = wrapper.getServerSideProps(
  (store) =>
    // destructuring context obj
    async ({ req, query }) => {
      await store.dispatch(getRooms(req, query.page));
    }
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM