Add Redux to a Next JS App
Tags: react, redux, nextjs, javascript
Published: 2020-11-15 15:15:53

In this article, I will go over how you can configure your Next JS application to use redux.

First set up your next js application
```
yarn create next-app next-redux
```

Next we install the desired packages
```
yarn add redux redux-thunk next-redux-wrapper react-redux
```

After that installation, create a redux folder in the root of your project, inside that folder add a types.js and store.js files, also add folders for actions and reducers.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/x6s10od6kwfvw4012kox.JPG)

In the types file, lets add a single type; for setting the name of the user

```js
export const SET_NAME = "SET_NAME"
```

In the reducers folder, add a `main.js` file, In this file we will create a reducer that will manage the main state of our app.

In this file we will initialize a main state with only one value for the name that defaults to guest. Then we will use a switch statement to detect the passed in action and value, the state gets updated based on the value received.

```js
import * as t from "../types";

const main = (state = {
    name: "guest",
}, action) => {
  switch(action.type){
    case t.SET_NAME:
      return { 
        ...state,
        name: action.payload
      };
    default:
      return {...state};
    }
}

export default main;
```

In the same reducers folder, we will add a `rootReducer.js` file, this file will combine all our reducers into one, it is most useful when you have multiple reducer files, for this article i will only be using a single reducer file, which is my main reducer.

```js
import { combineReducers } from "redux"
import main from "./main"

const rootReducer = combineReducers({
  main: main
})

export default rootReducer;
```

Next, we move to our `store.js` file

In this file we will create our redux store using `redux` and `next-redux-wrapper`, we will also add `redux-thunk` to allow us have extra functions before dispatching new values to our state.

```js
import { createStore, applyMiddleware, compose } from "redux"
import thunk from "redux-thunk"
import { createWrapper } from "next-redux-wrapper"
import rootReducer from "./reducers/rootReducer"

const middleware = [thunk]

const makeStore = () => createStore(rootReducer, compose(applyMiddleware(...middleware)))

export const wrapper = createWrapper(makeStore)
```

Now we will create our set name action, create a `main.js` file in the actions folder, inside it we will have a function that specifies the set name type with a new name value.

```js
import * as t from "../types";
import axios from "axios";
import { request } from "../../util/request";

export const setInfo = (name) => dispatch => {
  dispatch({
    type: t.SET_NAME,
    payload: name
  });
}
```

After you've done all of this, our directory should look like below

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zgpwf9mrs51kvpu3q79r.JPG)

Now move to your `_app.js` file, it should look like;
```js
import '../styles/globals.css'

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

export default MyApp

```

Update it to look like;
```js
import React from "react"
import { wrapper } from "../redux/store"

const MyApp = ({ Component, pageProps}) => (
  <Component {...pageProps} />
)

export default wrapper.withRedux(MyApp);
```

We've wrapped the app in the redux wrapper we created in our store file and passed props to it.
In our `index.js`, take out all the page content and leave an input box asking for a name.
```js
return (
    <div className={styles.container}>
      <p>Enter a Name :</p>
      <input 
        type="text">

        </input>
        <button>
          Submit
        </button>
    </div>
  )
```
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/52y5jfq9fzgdsqi248hx.JPG)

Next we add some state management for updating and storing the value of our form using `useState`, we also link our index page to our redux state and finally connect the actions using `mapDispatchToProps` and the state using `mapStateToProps`, the final `index.js` should look like below

```js
import { useState } from 'react'
import { connect } from "react-redux"
import { setInfo } from "../redux/actions/main"
import styles from '../styles/Home.module.css'

function Home(props) {
  const { name, setInfo } = props
  const [newName, setName] = useState("")

  return (
    <div className={styles.container}>
      <p>Enter a Name {name}:</p>
      <input 
        type="text" 
        value={newName} 
        onChange={(e) => setName(e.target.value)}>

        </input>
        <button onClick={() => setInfo(newName)}>
          Submit
        </button>
    </div>
  )
}

const mapStateToProps = state => {
 return { name: state.main.name }
}

const mapDispatchToProps = {
  setInfo
}

export default connect(mapStateToProps, mapDispatchToProps)(Home)
```

To be able to debug with [Redux Dev Tools](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd?hl=en), update your `store.js` code to;
```js
import { createStore, applyMiddleware, compose } from "redux"
import thunk from "redux-thunk"
import { createWrapper } from "next-redux-wrapper"
import rootReducer from "./reducers/rootReducer"

const middleware = [thunk]

const composeEnhancers =
  typeof window === 'object' &&
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?   
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;

const enhancer = composeEnhancers(applyMiddleware(...middleware));

const makeStore = () => createStore(rootReducer, enhancer)

export const wrapper = createWrapper(makeStore)
```

Your home page should now look like the below image, and changing the name should update the value of "guest"
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hkndcxwds916ezz8996z.JPG)

If you find this article helpful, you can also checkout other Next JS videos on [Youtube](https://www.youtube.com/watch?v=Vu3g4UHdCrQ&list=PLdyQLyByx6i2xprAWh2_AtMqp9zHQNN1U) or the [Full Stack Next JS Course on Udemy](https://www.udemy.com/course/full-stack-nextjs-with-redux-express-mongodb/?couponCode=9DAA0446C06878756A4B)