-
Notifications
You must be signed in to change notification settings - Fork 26.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add with-redux-toolkit example (#11358)
- Loading branch information
1 parent
044ddf4
commit e02b66a
Showing
8 changed files
with
222 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Redux Toolkit example | ||
|
||
This example shows how to integrate Redux with Toolkit in Next.js. | ||
|
||
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 | ||
|
||
## Deploy your own | ||
|
||
Deploy the example using [ZEIT Now](https://zeit.co/now): | ||
|
||
[![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) | ||
|
||
## How to use | ||
|
||
### Using `create-next-app` | ||
|
||
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: | ||
|
||
```bash | ||
npx create-next-app --example with-redux-toolkit with-redux-toolkit-app | ||
# or | ||
yarn create next-app --example with-redux-toolkit with-redux-toolkit-app | ||
``` | ||
|
||
### Download manually | ||
|
||
Download the example: | ||
|
||
```bash | ||
curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-redux-toolkit | ||
cd with-redux-toolkit | ||
``` | ||
|
||
Install it and run: | ||
|
||
```bash | ||
npm install | ||
npm run dev | ||
# or | ||
yarn | ||
yarn dev | ||
``` | ||
|
||
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)). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import React from 'react' | ||
import { useSelector, shallowEqual } from 'react-redux' | ||
|
||
const useClock = () => { | ||
return useSelector(state => { | ||
return { | ||
lastUpdate: state.lastUpdate, | ||
light: state.light, | ||
} | ||
}, shallowEqual) | ||
} | ||
|
||
const formatTime = time => { | ||
// cut off except hh:mm:ss | ||
return new Date(time).toJSON().slice(11, 19) | ||
} | ||
|
||
const Clock = () => { | ||
const { lastUpdate, light } = useClock() | ||
return ( | ||
<div className={light ? 'light' : ''}> | ||
{formatTime(lastUpdate)} | ||
<style jsx>{` | ||
div { | ||
padding: 15px; | ||
display: inline-block; | ||
color: #82fa58; | ||
font: 50px menlo, monaco, monospace; | ||
background-color: #000; | ||
} | ||
.light { | ||
background-color: #999; | ||
} | ||
`}</style> | ||
</div> | ||
) | ||
} | ||
|
||
export default Clock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import React from 'react' | ||
import { createAction } from '@reduxjs/toolkit' | ||
import { useSelector, useDispatch } from 'react-redux' | ||
|
||
const useCounter = () => { | ||
const count = useSelector(state => state.count) | ||
const dispatch = useDispatch() | ||
const increment = () => dispatch(createAction('INCREMENT')()) | ||
const decrement = () => dispatch(createAction('DECREMENT')()) | ||
const reset = () => dispatch(createAction('RESET')()) | ||
|
||
return { count, increment, decrement, reset } | ||
} | ||
|
||
const Counter = () => { | ||
const { count, increment, decrement, reset } = useCounter() | ||
return ( | ||
<div> | ||
<h1> | ||
Count: <span>{count}</span> | ||
</h1> | ||
<button onClick={increment}>+1</button> | ||
<button onClick={decrement}>-1</button> | ||
<button onClick={reset}>Reset</button> | ||
</div> | ||
) | ||
} | ||
|
||
export default Counter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { useEffect, useRef } from 'react' | ||
|
||
// https://overreacted.io/making-setinterval-declarative-with-react-hooks/ | ||
const useInterval = (callback, delay) => { | ||
const savedCallback = useRef() | ||
useEffect(() => { | ||
savedCallback.current = callback | ||
}, [callback]) | ||
useEffect(() => { | ||
const handler = (...args) => savedCallback.current(...args) | ||
|
||
if (delay !== null) { | ||
const id = setInterval(handler, delay) | ||
return () => clearInterval(id) | ||
} | ||
}, [delay]) | ||
} | ||
|
||
export default useInterval |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"name": "with-redux", | ||
"version": "1.0.0", | ||
"scripts": { | ||
"dev": "next", | ||
"build": "next build", | ||
"start": "next start" | ||
}, | ||
"dependencies": { | ||
"@reduxjs/toolkit": "^1.2.5", | ||
"next": "latest", | ||
"react": "^16.9.0", | ||
"react-dom": "^16.9.0", | ||
"react-redux": "^7.1.0", | ||
"redux": "^3.6.0", | ||
"redux-devtools-extension": "^2.13.2" | ||
}, | ||
"license": "ISC" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from 'react' | ||
import { Provider } from 'react-redux' | ||
import { store } from '../store' | ||
|
||
const MyApp = ({ Component, pageProps }) => { | ||
return ( | ||
<Provider store={store}> | ||
<Component {...pageProps} /> | ||
</Provider> | ||
) | ||
} | ||
|
||
export default MyApp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import React from 'react' | ||
import { createAction } from '@reduxjs/toolkit' | ||
import { connect } from 'react-redux' | ||
import useInterval from '../lib/useInterval' | ||
import Clock from '../components/clock' | ||
import Counter from '../components/counter' | ||
|
||
const tick = createAction('TICK', light => { | ||
return { | ||
payload: { | ||
light: light, | ||
lastUpdate: Date.now(), | ||
}, | ||
} | ||
}) | ||
|
||
const IndexPage = ({ dispatch }) => { | ||
// Use state or dispatch here | ||
|
||
// Tick the time every second | ||
useInterval(() => { | ||
dispatch(tick(true)) | ||
}, 1000) | ||
return ( | ||
<> | ||
<Clock /> | ||
<Counter /> | ||
</> | ||
) | ||
} | ||
|
||
export default connect(state => state)(IndexPage) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { configureStore, createReducer } from '@reduxjs/toolkit' | ||
|
||
const initialState = { | ||
light: false, | ||
lastUpdate: 0, | ||
count: 0, | ||
} | ||
|
||
const reducer = createReducer(initialState, { | ||
TICK: (state, action) => ({ | ||
...state, | ||
lastUpdate: action.payload.lastUpdate, | ||
light: !!action.light, | ||
}), | ||
INCREMENT: (state, action) => ({ ...state, count: state.count + 1 }), | ||
DECREMENT: (state, action) => ({ ...state, count: state.count - 1 }), | ||
RESET: (state, action) => ({ ...state, count: initialState.count }), | ||
}) | ||
|
||
const initializeStore = (preloadedState = initialState) => { | ||
return configureStore({ | ||
reducer, | ||
preloadedState, | ||
}) | ||
} | ||
export const store = initializeStore() |