From e02b66a52c0a9bb837845e6ec4e6356b3ee1697f Mon Sep 17 00:00:00 2001
From: Jazib Jafri <42325130+JazibJafri@users.noreply.github.com>
Date: Thu, 26 Mar 2020 23:15:40 +0500
Subject: [PATCH] Add with-redux-toolkit example (#11358)
---
examples/with-redux-toolkit/README.md | 44 +++++++++++++++++++
.../with-redux-toolkit/components/clock.js | 40 +++++++++++++++++
.../with-redux-toolkit/components/counter.js | 29 ++++++++++++
.../with-redux-toolkit/lib/useInterval.js | 19 ++++++++
examples/with-redux-toolkit/package.json | 19 ++++++++
examples/with-redux-toolkit/pages/_app.js | 13 ++++++
examples/with-redux-toolkit/pages/index.js | 32 ++++++++++++++
examples/with-redux-toolkit/store.js | 26 +++++++++++
8 files changed, 222 insertions(+)
create mode 100644 examples/with-redux-toolkit/README.md
create mode 100644 examples/with-redux-toolkit/components/clock.js
create mode 100644 examples/with-redux-toolkit/components/counter.js
create mode 100644 examples/with-redux-toolkit/lib/useInterval.js
create mode 100644 examples/with-redux-toolkit/package.json
create mode 100644 examples/with-redux-toolkit/pages/_app.js
create mode 100644 examples/with-redux-toolkit/pages/index.js
create mode 100644 examples/with-redux-toolkit/store.js
diff --git a/examples/with-redux-toolkit/README.md b/examples/with-redux-toolkit/README.md
new file mode 100644
index 0000000000000..3c3cbae41e058
--- /dev/null
+++ b/examples/with-redux-toolkit/README.md
@@ -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)).
diff --git a/examples/with-redux-toolkit/components/clock.js b/examples/with-redux-toolkit/components/clock.js
new file mode 100644
index 0000000000000..d394d9376cf26
--- /dev/null
+++ b/examples/with-redux-toolkit/components/clock.js
@@ -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 (
+
+ {formatTime(lastUpdate)}
+
+
+ )
+}
+
+export default Clock
diff --git a/examples/with-redux-toolkit/components/counter.js b/examples/with-redux-toolkit/components/counter.js
new file mode 100644
index 0000000000000..05ab067e968e0
--- /dev/null
+++ b/examples/with-redux-toolkit/components/counter.js
@@ -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 (
+
+
+ Count: {count}
+
+
+
+
+
+ )
+}
+
+export default Counter
diff --git a/examples/with-redux-toolkit/lib/useInterval.js b/examples/with-redux-toolkit/lib/useInterval.js
new file mode 100644
index 0000000000000..066d08ee254b5
--- /dev/null
+++ b/examples/with-redux-toolkit/lib/useInterval.js
@@ -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
diff --git a/examples/with-redux-toolkit/package.json b/examples/with-redux-toolkit/package.json
new file mode 100644
index 0000000000000..91f06b4bddce9
--- /dev/null
+++ b/examples/with-redux-toolkit/package.json
@@ -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"
+}
diff --git a/examples/with-redux-toolkit/pages/_app.js b/examples/with-redux-toolkit/pages/_app.js
new file mode 100644
index 0000000000000..025a8be8c9b98
--- /dev/null
+++ b/examples/with-redux-toolkit/pages/_app.js
@@ -0,0 +1,13 @@
+import React from 'react'
+import { Provider } from 'react-redux'
+import { store } from '../store'
+
+const MyApp = ({ Component, pageProps }) => {
+ return (
+
+
+
+ )
+}
+
+export default MyApp
diff --git a/examples/with-redux-toolkit/pages/index.js b/examples/with-redux-toolkit/pages/index.js
new file mode 100644
index 0000000000000..30da73b0c7efa
--- /dev/null
+++ b/examples/with-redux-toolkit/pages/index.js
@@ -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 (
+ <>
+
+
+ >
+ )
+}
+
+export default connect(state => state)(IndexPage)
diff --git a/examples/with-redux-toolkit/store.js b/examples/with-redux-toolkit/store.js
new file mode 100644
index 0000000000000..9c2a9d3c05e76
--- /dev/null
+++ b/examples/with-redux-toolkit/store.js
@@ -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()