├── .gitignore
├── README.md
├── package-lock.json
├── package.json
├── pages
├── _app.jsx
└── index.jsx
└── redux
├── actions
└── counterActions.js
├── reducers
├── counterReducer.js
└── rootReducer.js
└── store.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .next
2 |
3 | node_modules
4 |
5 | .idea
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Nextjs-React-Redux-Example
2 |
3 | A Simple Counter App made with next.js, react and redux.
4 |
5 | To run the app:
6 |
7 | ```
8 | npm install
9 | npm run dev
10 | ```
11 |
12 | [Detailed Explanation](https://dev.to/waqasabbasi/server-side-rendered-app-with-next-js-react-and-redux-38gf)
13 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hello-next",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "next",
8 | "build": "next build",
9 | "start": "next start"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "dependencies": {
15 | "next": "^9.1.7",
16 | "next-redux-wrapper": "^4.0.1",
17 | "react": "^16.12.0",
18 | "react-dom": "^16.12.0",
19 | "react-redux": "^7.1.3",
20 | "redux": "^4.0.5"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/pages/_app.jsx:
--------------------------------------------------------------------------------
1 | import App from 'next/app';
2 | import {Provider} from 'react-redux';
3 | import React from 'react';
4 | import withRedux from "next-redux-wrapper";
5 | import store from '../redux/store';
6 |
7 | class MyApp extends App {
8 |
9 | static async getInitialProps({Component, ctx}) {
10 | const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {};
11 |
12 | //Anything returned here can be accessed by the client
13 | return {pageProps: pageProps};
14 | }
15 |
16 | render() {
17 | //Page props that were returned from 'getInitialProps' are stored in the props i.e. pageprops
18 | const {Component, pageProps, store} = this.props;
19 |
20 | return (
21 |
22 |
23 |
24 | );
25 | }
26 | }
27 |
28 | //makeStore function that returns a new store for every request
29 | const makeStore = () => store;
30 |
31 | //withRedux wrapper that passes the store to the App Component
32 | export default withRedux(makeStore)(MyApp);
33 |
34 |
--------------------------------------------------------------------------------
/pages/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {connect} from 'react-redux';
3 | import {decrementCounter, incrementCounter} from '../redux/actions/counterActions';
4 |
5 | class App extends React.Component {
6 |
7 | static getInitialProps({store}) {}
8 |
9 | constructor(props) {
10 | super(props);
11 | }
12 |
13 | render() {
14 | return (
15 |
16 |
17 |
18 |
{this.props.counter}
19 |
20 | );
21 | }
22 | }
23 |
24 | const mapStateToProps = state => ({
25 | counter: state.counter.value
26 | });
27 |
28 | const mapDispatchToProps = {
29 | incrementCounter: incrementCounter,
30 | decrementCounter: decrementCounter,
31 | };
32 | export default connect(mapStateToProps, mapDispatchToProps)(App);
33 |
34 |
--------------------------------------------------------------------------------
/redux/actions/counterActions.js:
--------------------------------------------------------------------------------
1 | //Action Types
2 | export const INCREMENT_COUNTER = "INCREMENT_COUNTER";
3 | export const DECREMENT_COUNTER = "DECREMENT_COUNTER";
4 |
5 |
6 | //Action Creator
7 | export const incrementCounter = () => ({
8 | type: INCREMENT_COUNTER
9 | });
10 |
11 | export const decrementCounter = () => ({
12 | type: DECREMENT_COUNTER
13 | });
14 |
--------------------------------------------------------------------------------
/redux/reducers/counterReducer.js:
--------------------------------------------------------------------------------
1 | import {DECREMENT_COUNTER, INCREMENT_COUNTER} from '../actions/counterActions';
2 |
3 | const counterReducer = (state = {value: 0}, action) => {
4 | switch (action.type) {
5 | case INCREMENT_COUNTER:
6 | return {...state, value: state.value + 1};
7 | case DECREMENT_COUNTER:
8 | return {...state, value: state.value - 1};
9 | default:
10 | return {...state};
11 | }
12 | };
13 |
14 | export default counterReducer;
15 |
--------------------------------------------------------------------------------
/redux/reducers/rootReducer.js:
--------------------------------------------------------------------------------
1 | import counterReducer from './counterReducer';
2 | import {combineReducers} from 'redux';
3 |
4 | const rootReducer = combineReducers({
5 | counter: counterReducer
6 | });
7 |
8 | export default rootReducer;
9 |
--------------------------------------------------------------------------------
/redux/store.js:
--------------------------------------------------------------------------------
1 | import {createStore} from 'redux';
2 | import rootReducer from './reducers/rootReducer';
3 |
4 | const store = createStore(rootReducer);
5 |
6 | export default store;
7 |
8 |
9 |
--------------------------------------------------------------------------------