├── .gitignore ├── README.md ├── package.json ├── pages ├── _app.js ├── api │ └── hello.js └── index.js ├── public ├── favicon.ico └── vercel.svg ├── styles ├── Home.module.css └── globals.css └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # How I Manage State in React 2 | 3 | When I'm building a React app, how do I manage state? 4 | 5 | ## App State 6 | 7 | Keep state as low as possible. 8 | 9 | 1. Local State 10 | 2. Lift State 11 | 3. Global State (with contexts) 12 | 13 | Once you are dealing with Global State, you're welcome to use MobX, Redux, Overmind, Zustand, Recoil, etc... or just stick with `useState`. 14 | 15 | ## External Data 16 | 17 | React Query, SWR, Apollo Client, urql 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-state", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start" 9 | }, 10 | "dependencies": { 11 | "next": "9.5.3", 12 | "react": "16.13.1", 13 | "react-dom": "16.13.1", 14 | "react-query": "^2.23.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /pages/_app.js: -------------------------------------------------------------------------------- 1 | import '../styles/globals.css' 2 | 3 | function MyApp({ Component, pageProps }) { 4 | return 5 | } 6 | 7 | export default MyApp 8 | -------------------------------------------------------------------------------- /pages/api/hello.js: -------------------------------------------------------------------------------- 1 | // Next.js API route support: https://nextjs.org/docs/api-routes/introduction 2 | 3 | export default (req, res) => { 4 | res.statusCode = 200 5 | res.json({ name: 'John Doe' }) 6 | } 7 | -------------------------------------------------------------------------------- /pages/index.js: -------------------------------------------------------------------------------- 1 | import { useState, memo, createContext, useContext } from "react"; 2 | import { useQuery } from "react-query"; 3 | import styles from "../styles/Home.module.css"; 4 | 5 | export default function Home() { 6 | return ( 7 | 8 | 9 | 10 | ); 11 | } 12 | 13 | const HomeContent = memo(() => { 14 | return ( 15 |
16 | 17 | 18 |
19 | ); 20 | }); 21 | 22 | const CountryContext = createContext(); 23 | 24 | function CountryProvider({ children }) { 25 | const [country, setCountry] = useState("CA"); 26 | 27 | return ( 28 | 29 | {children} 30 | 31 | ); 32 | } 33 | 34 | async function fetchCountry(country) { 35 | const response = await fetch( 36 | `https://restcountries.eu/rest/v2/alpha/${country}` 37 | ); 38 | const data = await response.json(); 39 | return data; 40 | } 41 | 42 | function CountryDetails() { 43 | const { country } = useContext(CountryContext); 44 | const { data, isLoading, error } = useQuery([country], fetchCountry); 45 | 46 | if (isLoading) return loading...; 47 | if (error) return oop!! error occurred; 48 | 49 | return ( 50 |
51 |

{country}

52 |
{JSON.stringify(data, null, 2)}
53 |
54 | ); 55 | } 56 | 57 | function CountryPicker() { 58 | const { country, setCountry } = useContext(CountryContext); 59 | 60 | return ( 61 | 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leighhalliday/managing-state-react/8e15afdaf961b784a4c01848e816382e9971f3f4/public/favicon.ico -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /styles/Home.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | min-height: 100vh; 3 | padding: 0 0.5rem; 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: center; 7 | align-items: center; 8 | } 9 | -------------------------------------------------------------------------------- /styles/globals.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | padding: 0; 4 | margin: 0; 5 | font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, 6 | Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; 7 | } 8 | 9 | a { 10 | color: inherit; 11 | text-decoration: none; 12 | } 13 | 14 | * { 15 | box-sizing: border-box; 16 | } 17 | --------------------------------------------------------------------------------