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.
In the types file, lets add a single type; for setting the name of the user
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.
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.
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.
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.
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
});
}
Now move to your _app.js
file, it should look like;
import '../styles/globals.css'
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default MyApp
Update it to look like;
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.
return (
<div className={styles.container}>
<p>Enter a Name :</p>
<input
type="text">
</input>
<button>
Submit
</button>
</div>
)
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
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, update your store.js
code to;
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”.