Skip to content

Commit e02b66a

Browse files
authored
Add with-redux-toolkit example (#11358)
1 parent 044ddf4 commit e02b66a

File tree

8 files changed

+222
-0
lines changed

8 files changed

+222
-0
lines changed

examples/with-redux-toolkit/README.md

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Redux Toolkit example
2+
3+
This example shows how to integrate Redux with Toolkit in Next.js.
4+
5+
Redux toolkit makes it easier to configure a redux store, create reducers or dispatch actions, along with some default middlewares. This example demonstrates each of these tasks with Next.js
6+
7+
## Deploy your own
8+
9+
Deploy the example using [ZEIT Now](https://zeit.co/now):
10+
11+
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/next.js/tree/canary/examples/with-redux-toolkit)
12+
13+
## How to use
14+
15+
### Using `create-next-app`
16+
17+
Execute [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:
18+
19+
```bash
20+
npx create-next-app --example with-redux-toolkit with-redux-toolkit-app
21+
# or
22+
yarn create next-app --example with-redux-toolkit with-redux-toolkit-app
23+
```
24+
25+
### Download manually
26+
27+
Download the example:
28+
29+
```bash
30+
curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-redux-toolkit
31+
cd with-redux-toolkit
32+
```
33+
34+
Install it and run:
35+
36+
```bash
37+
npm install
38+
npm run dev
39+
# or
40+
yarn
41+
yarn dev
42+
```
43+
44+
Deploy it to the cloud with [ZEIT Now](https://zeit.co/import?filter=next.js&utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react'
2+
import { useSelector, shallowEqual } from 'react-redux'
3+
4+
const useClock = () => {
5+
return useSelector(state => {
6+
return {
7+
lastUpdate: state.lastUpdate,
8+
light: state.light,
9+
}
10+
}, shallowEqual)
11+
}
12+
13+
const formatTime = time => {
14+
// cut off except hh:mm:ss
15+
return new Date(time).toJSON().slice(11, 19)
16+
}
17+
18+
const Clock = () => {
19+
const { lastUpdate, light } = useClock()
20+
return (
21+
<div className={light ? 'light' : ''}>
22+
{formatTime(lastUpdate)}
23+
<style jsx>{`
24+
div {
25+
padding: 15px;
26+
display: inline-block;
27+
color: #82fa58;
28+
font: 50px menlo, monaco, monospace;
29+
background-color: #000;
30+
}
31+
32+
.light {
33+
background-color: #999;
34+
}
35+
`}</style>
36+
</div>
37+
)
38+
}
39+
40+
export default Clock
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import React from 'react'
2+
import { createAction } from '@reduxjs/toolkit'
3+
import { useSelector, useDispatch } from 'react-redux'
4+
5+
const useCounter = () => {
6+
const count = useSelector(state => state.count)
7+
const dispatch = useDispatch()
8+
const increment = () => dispatch(createAction('INCREMENT')())
9+
const decrement = () => dispatch(createAction('DECREMENT')())
10+
const reset = () => dispatch(createAction('RESET')())
11+
12+
return { count, increment, decrement, reset }
13+
}
14+
15+
const Counter = () => {
16+
const { count, increment, decrement, reset } = useCounter()
17+
return (
18+
<div>
19+
<h1>
20+
Count: <span>{count}</span>
21+
</h1>
22+
<button onClick={increment}>+1</button>
23+
<button onClick={decrement}>-1</button>
24+
<button onClick={reset}>Reset</button>
25+
</div>
26+
)
27+
}
28+
29+
export default Counter
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { useEffect, useRef } from 'react'
2+
3+
// https://overreacted.io/making-setinterval-declarative-with-react-hooks/
4+
const useInterval = (callback, delay) => {
5+
const savedCallback = useRef()
6+
useEffect(() => {
7+
savedCallback.current = callback
8+
}, [callback])
9+
useEffect(() => {
10+
const handler = (...args) => savedCallback.current(...args)
11+
12+
if (delay !== null) {
13+
const id = setInterval(handler, delay)
14+
return () => clearInterval(id)
15+
}
16+
}, [delay])
17+
}
18+
19+
export default useInterval
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "with-redux",
3+
"version": "1.0.0",
4+
"scripts": {
5+
"dev": "next",
6+
"build": "next build",
7+
"start": "next start"
8+
},
9+
"dependencies": {
10+
"@reduxjs/toolkit": "^1.2.5",
11+
"next": "latest",
12+
"react": "^16.9.0",
13+
"react-dom": "^16.9.0",
14+
"react-redux": "^7.1.0",
15+
"redux": "^3.6.0",
16+
"redux-devtools-extension": "^2.13.2"
17+
},
18+
"license": "ISC"
19+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React from 'react'
2+
import { Provider } from 'react-redux'
3+
import { store } from '../store'
4+
5+
const MyApp = ({ Component, pageProps }) => {
6+
return (
7+
<Provider store={store}>
8+
<Component {...pageProps} />
9+
</Provider>
10+
)
11+
}
12+
13+
export default MyApp
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import React from 'react'
2+
import { createAction } from '@reduxjs/toolkit'
3+
import { connect } from 'react-redux'
4+
import useInterval from '../lib/useInterval'
5+
import Clock from '../components/clock'
6+
import Counter from '../components/counter'
7+
8+
const tick = createAction('TICK', light => {
9+
return {
10+
payload: {
11+
light: light,
12+
lastUpdate: Date.now(),
13+
},
14+
}
15+
})
16+
17+
const IndexPage = ({ dispatch }) => {
18+
// Use state or dispatch here
19+
20+
// Tick the time every second
21+
useInterval(() => {
22+
dispatch(tick(true))
23+
}, 1000)
24+
return (
25+
<>
26+
<Clock />
27+
<Counter />
28+
</>
29+
)
30+
}
31+
32+
export default connect(state => state)(IndexPage)

examples/with-redux-toolkit/store.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { configureStore, createReducer } from '@reduxjs/toolkit'
2+
3+
const initialState = {
4+
light: false,
5+
lastUpdate: 0,
6+
count: 0,
7+
}
8+
9+
const reducer = createReducer(initialState, {
10+
TICK: (state, action) => ({
11+
...state,
12+
lastUpdate: action.payload.lastUpdate,
13+
light: !!action.light,
14+
}),
15+
INCREMENT: (state, action) => ({ ...state, count: state.count + 1 }),
16+
DECREMENT: (state, action) => ({ ...state, count: state.count - 1 }),
17+
RESET: (state, action) => ({ ...state, count: initialState.count }),
18+
})
19+
20+
const initializeStore = (preloadedState = initialState) => {
21+
return configureStore({
22+
reducer,
23+
preloadedState,
24+
})
25+
}
26+
export const store = initializeStore()

0 commit comments

Comments
 (0)