Skip to content

Commit

Permalink
Initial commit from Create Next App
Browse files Browse the repository at this point in the history
  • Loading branch information
sonnysangha committed May 17, 2021
0 parents commit afcd6c5
Show file tree
Hide file tree
Showing 14 changed files with 2,313 additions and 0 deletions.
34 changes: 34 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# vercel
.vercel
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Redux Toolkit example

This example shows how to integrate Next.js with [Redux Toolkit](https://redux-toolkit.js.org).

The **Redux Toolkit** is intended to be the standard way to write Redux logic (create actions and reducers, setup the store with some default middlewares like redux devtools extension). This example demonstrates each of these features with Next.js

## Deploy your own

Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example):

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-redux-toolkit&project-name=with-redux-toolkit&repository-name=with-redux-toolkit)

## How to use

Execute [`create-next-app`](https://github.com/vercel/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
```

Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).

### TypeScript Setup (optional)

If you haven't already added [TypeScript](https://www.typescriptlang.org/) to your project, follow the [steps in the Next.js documentation](https://nextjs.org/docs/basic-features/typescript). If you are new to TypeScript, go through the Next.js [learning lesson on TypeScript](https://nextjs.org/learn/excel/TypeScript).

Once TypeScript is added, follow the instructions given on the Redux Toolkit [documentation](https://redux-toolkit.js.org/tutorials/TypeScript) to set up and use Redux Toolkit and React-Redux with TypeScript
17 changes: 17 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "with-redux-toolkit",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@reduxjs/toolkit": "1.5.0",
"next": "latest",
"react": "17.0.1",
"react-dom": "17.0.1",
"react-redux": "7.2.2"
},
"license": "MIT"
}
Binary file added public/favicon.ico
Binary file not shown.
1 change: 1 addition & 0 deletions public/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/app/store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'

export const store = configureStore({
reducer: {
counter: counterReducer,
},
})
60 changes: 60 additions & 0 deletions src/features/counter/Counter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { useState } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import {
decrement,
increment,
incrementByAmount,
incrementAsync,
selectCount,
} from './counterSlice'
import styles from './Counter.module.css'

export function Counter() {
const count = useSelector(selectCount)
const dispatch = useDispatch()
const [incrementAmount, setIncrementAmount] = useState('2')

return (
<div>
<div className={styles.row}>
<button
className={styles.button}
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
+
</button>
<span className={styles.value}>{count}</span>
<button
className={styles.button}
aria-label="Decrement value"
onClick={() => dispatch(decrement())}
>
-
</button>
</div>
<div className={styles.row}>
<input
className={styles.textbox}
aria-label="Set increment amount"
value={incrementAmount}
onChange={(e) => setIncrementAmount(e.target.value)}
/>
<button
className={styles.button}
onClick={() =>
dispatch(incrementByAmount(Number(incrementAmount) || 0))
}
>
Add Amount
</button>
<button
className={styles.asyncButton}
onClick={() => dispatch(incrementAsync(Number(incrementAmount) || 0))}
>
Add Async
</button>
</div>
</div>
)
}
75 changes: 75 additions & 0 deletions src/features/counter/Counter.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
.row {
display: flex;
align-items: center;
justify-content: center;
}

.row:not(:last-child) {
margin-bottom: 16px;
}

.value {
font-size: 78px;
padding-left: 16px;
padding-right: 16px;
margin-top: 2px;
font-family: 'Courier New', Courier, monospace;
}

.button {
appearance: none;
background: none;
font-size: 32px;
padding-left: 12px;
padding-right: 12px;
outline: none;
border: 2px solid transparent;
color: rgb(112, 76, 182);
padding-bottom: 4px;
cursor: pointer;
background-color: rgba(112, 76, 182, 0.1);
border-radius: 2px;
transition: all 0.15s;
}

.textbox {
font-size: 32px;
padding: 2px;
width: 64px;
text-align: center;
margin-right: 8px;
}

.button:hover,
.button:focus {
border: 2px solid rgba(112, 76, 182, 0.4);
}

.button:active {
background-color: rgba(112, 76, 182, 0.2);
}

.asyncButton {
composes: button;
position: relative;
margin-left: 8px;
}

.asyncButton:after {
content: '';
background-color: rgba(112, 76, 182, 0.15);
display: block;
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
opacity: 0;
transition: width 1s linear, opacity 0.5s ease 1s;
}

.asyncButton:active:after {
width: 0%;
opacity: 1;
transition: 0s;
}
45 changes: 45 additions & 0 deletions src/features/counter/counterSlice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { createSlice } from '@reduxjs/toolkit'

const initialState = {
value: 0,
}

export const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the Immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based on those changes
state.value += 1
},
decrement: (state) => {
state.value -= 1
},
// Use the PayloadAction type to declare the contents of `action.payload`
incrementByAmount: (state, action) => {
state.value += action.payload
},
},
})

export const { increment, decrement, incrementByAmount } = counterSlice.actions

// The function below is called a thunk and allows us to perform async logic. It
// can be dispatched like a regular action: `dispatch(incrementAsync(10))`. This
// will call the thunk with the `dispatch` function as the first argument. Async
// code can then be executed and other actions can be dispatched
export const incrementAsync = (amount) => (dispatch) => {
setTimeout(() => {
dispatch(incrementByAmount(amount))
}, 1000)
}

// The function below is called a selector and allows us to select a value from
// the state. Selectors can also be defined inline where they're used instead of
// in the slice file. For example: `useSelector((state: RootState) => state.counter.value)`
export const selectCount = (state) => state.counter.value

export default counterSlice.reducer
13 changes: 13 additions & 0 deletions src/pages/_app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Provider } from 'react-redux'
import { store } from '../app/store'
import '../styles/globals.css'

const MyApp = ({ Component, pageProps }) => {
return (
<Provider store={store}>
<Component {...pageProps} />
</Provider>
)
}

export default MyApp
59 changes: 59 additions & 0 deletions src/pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Counter } from '../features/counter/Counter'
import styles from '../styles/Home.module.css'
import Head from 'next/head'

export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>Redux Toolkit</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<header className={styles.header}>
<img src="/logo.svg" className={styles.logo} alt="logo" />
<Counter />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<span>
<span>Learn </span>
<a
className={styles.link}
href="https://reactjs.org/"
target="_blank"
rel="noopener noreferrer"
>
React
</a>
<span>, </span>
<a
className={styles.link}
href="https://redux.js.org/"
target="_blank"
rel="noopener noreferrer"
>
Redux
</a>
<span>, </span>
<a
className={styles.link}
href="https://redux-toolkit.js.org/"
target="_blank"
rel="noopener noreferrer"
>
Redux Toolkit
</a>
,<span> and </span>
<a
className={styles.link}
href="https://react-redux.js.org/"
target="_blank"
rel="noopener noreferrer"
>
React Redux
</a>
</span>
</header>
</div>
)
}
39 changes: 39 additions & 0 deletions src/styles/Home.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.container {
text-align: center;
}

.logo {
height: 40vmin;
pointer-events: none;
}

.header {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
}

.link {
color: rgb(112, 76, 182);
}

@media (prefers-reduced-motion: no-preference) {
.logo {
animation: logo-float infinite 3s ease-in-out;
}
}

@keyframes logo-float {
0% {
transform: translateY(0);
}
50% {
transform: translateY(10px);
}
100% {
transform: translateY(0px);
}
}
Loading

0 comments on commit afcd6c5

Please sign in to comment.