mirror of
https://github.com/seigler/presentation-react-state-management
synced 2025-07-27 01:36:09 +00:00
start useState
This commit is contained in:
parent
98ab1bce45
commit
2a4cd44504
8 changed files with 168 additions and 18 deletions
22
README.md
22
README.md
|
@ -10,10 +10,24 @@ Joshua Seigler - October 2022
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
`npm run start` for development or local hosting
|
NPM scripts (run with <code>npm run <em>scriptname</em></code>)
|
||||||
|
|
||||||
`npm run build` to populate `./dist` with a packaged build, ready for upload
|
### `start`
|
||||||
|
|
||||||
`npm run clean` to delete `./dist` and various cache folders
|
Run the project locally at http://localhost:1234 and watch for code changes
|
||||||
|
|
||||||
`npm run publish` to upload `./dist` to the GitHub Pages branch
|
### `publish`
|
||||||
|
|
||||||
|
Runs scripts `clean`, `build`, and `deploy` in order.
|
||||||
|
|
||||||
|
### `clean`
|
||||||
|
|
||||||
|
Deletes `./dist`
|
||||||
|
|
||||||
|
### `build`
|
||||||
|
|
||||||
|
Populate `./dist` with a packaged build, ready for upload
|
||||||
|
|
||||||
|
### `deploy`
|
||||||
|
|
||||||
|
Replace the contents of branch `gh-pages` with the contents of `./dist`
|
||||||
|
|
43
package-lock.json
generated
43
package-lock.json
generated
|
@ -11,6 +11,7 @@
|
||||||
"@types/react": "^18.0.21",
|
"@types/react": "^18.0.21",
|
||||||
"@types/react-dom": "^18.0.6",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
|
"localforage": "^1.10.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-router": "^6.4.2",
|
"react-router": "^6.4.2",
|
||||||
"react-router-dom": "^6.4.2",
|
"react-router-dom": "^6.4.2",
|
||||||
|
@ -2003,6 +2004,11 @@
|
||||||
"entities": "^3.0.1"
|
"entities": "^3.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/immediate": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
|
||||||
|
},
|
||||||
"node_modules/import-fresh": {
|
"node_modules/import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||||
|
@ -2054,6 +2060,14 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lie": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
|
||||||
|
"dependencies": {
|
||||||
|
"immediate": "~3.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lightningcss": {
|
"node_modules/lightningcss": {
|
||||||
"version": "1.16.0",
|
"version": "1.16.0",
|
||||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.16.0.tgz",
|
||||||
|
@ -2288,6 +2302,14 @@
|
||||||
"integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==",
|
"integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/localforage": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
|
||||||
|
"dependencies": {
|
||||||
|
"lie": "3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/lodash": {
|
"node_modules/lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
@ -4155,6 +4177,11 @@
|
||||||
"entities": "^3.0.1"
|
"entities": "^3.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"immediate": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="
|
||||||
|
},
|
||||||
"import-fresh": {
|
"import-fresh": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||||
|
@ -4194,6 +4221,14 @@
|
||||||
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"lie": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==",
|
||||||
|
"requires": {
|
||||||
|
"immediate": "~3.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"lightningcss": {
|
"lightningcss": {
|
||||||
"version": "1.16.0",
|
"version": "1.16.0",
|
||||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.16.0.tgz",
|
||||||
|
@ -4300,6 +4335,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"localforage": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz",
|
||||||
|
"integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==",
|
||||||
|
"requires": {
|
||||||
|
"lie": "3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"lodash": {
|
"lodash": {
|
||||||
"version": "4.17.21",
|
"version": "4.17.21",
|
||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
|
|
@ -8,8 +8,9 @@
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"start": "parcel",
|
"start": "parcel",
|
||||||
"build": "parcel build",
|
"build": "parcel build",
|
||||||
"deploy": "git-directory-deploy --directory dist/",
|
"deploy": "echo > ./dist/.nojekyll && git-directory-deploy --directory dist/",
|
||||||
"clean": "rm -rf ./dist ./.cache ./.parcel-cache"
|
"clean": "rm -rf ./dist",
|
||||||
|
"publish": "npm run clean && npm run build && npm run deploy"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"presentation",
|
"presentation",
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
"@types/react": "^18.0.21",
|
"@types/react": "^18.0.21",
|
||||||
"@types/react-dom": "^18.0.6",
|
"@types/react-dom": "^18.0.6",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
|
"localforage": "^1.10.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-router": "^6.4.2",
|
"react-router": "^6.4.2",
|
||||||
"react-router-dom": "^6.4.2",
|
"react-router-dom": "^6.4.2",
|
||||||
|
|
53
src/App.tsx
Normal file
53
src/App.tsx
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { Link, NavLink, Route, Routes } from 'react-router-dom'
|
||||||
|
import { strategies } from './strategies'
|
||||||
|
import { ErrorPage } from './error-page'
|
||||||
|
|
||||||
|
export function App() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<header>
|
||||||
|
<h1>React State Management</h1>
|
||||||
|
<nav>
|
||||||
|
<Link to="/">Introduction</Link>
|
||||||
|
{strategies.map(({ name }) => (
|
||||||
|
<NavLink
|
||||||
|
key={name}
|
||||||
|
to={name}
|
||||||
|
className={({ isActive }) => (isActive ? 'isActive' : '')}>
|
||||||
|
{name}
|
||||||
|
</NavLink>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
<hr />
|
||||||
|
<Routes>
|
||||||
|
<Route path="/" errorElement={<ErrorPage />}>
|
||||||
|
<Route index element={<Introduction />} />
|
||||||
|
{strategies.map(({ name, component: StrategyComponent }) => (
|
||||||
|
<Route key={name} path={name} element={<StrategyComponent />} />
|
||||||
|
))}
|
||||||
|
<Route path="*" element={<NotFound />} />
|
||||||
|
</Route>
|
||||||
|
</Routes>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function NotFound() {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<h2>You took a wrong turn</h2>
|
||||||
|
<p>There's nothing here.</p>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Introduction() {
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<h2>Introduction</h2>
|
||||||
|
<p>Here are some ways to store state in a React Application.</p>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,21 +1,21 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import { createRoot } from 'react-dom/client'
|
||||||
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
|
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
|
||||||
import { ErrorPage } from './error-page'
|
import { ErrorPage } from './error-page'
|
||||||
import { Root } from './routes/root'
|
import { App } from './App'
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/*',
|
||||||
element: <Root />,
|
element: <App />,
|
||||||
errorElement: <ErrorPage />
|
errorElement: <ErrorPage />
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
const appEntry = document.getElementById('app')
|
const appEntry = document.getElementById('app')
|
||||||
ReactDOM.render(
|
const root = createRoot(appEntry!)
|
||||||
|
root.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<RouterProvider router={router} />
|
<RouterProvider router={router} />
|
||||||
</React.StrictMode>,
|
</React.StrictMode>
|
||||||
appEntry
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
export function Root() {
|
|
||||||
return <h1>React State Management</h1>
|
|
||||||
}
|
|
3
src/strategies/index.ts
Normal file
3
src/strategies/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import { UseState } from "./useState";
|
||||||
|
|
||||||
|
export const strategies = [{ name: 'useState', component: UseState }]
|
40
src/strategies/useState.tsx
Normal file
40
src/strategies/useState.tsx
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
|
||||||
|
type Todo = {
|
||||||
|
id: string
|
||||||
|
text: string
|
||||||
|
status: 'incomplete' | 'complete' | 'hidden'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function UseState() {
|
||||||
|
const [todos, setTodos] = useState<Todo[]>([])
|
||||||
|
const [newTodoText, setNewTodoText] = useState('')
|
||||||
|
|
||||||
|
function addTodo() {
|
||||||
|
const newTodo = {
|
||||||
|
id: crypto.randomUUID(),
|
||||||
|
text: newTodoText,
|
||||||
|
status: 'incomplete' as const
|
||||||
|
}
|
||||||
|
setTodos((t) => [...t, newTodo])
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
addTodo()
|
||||||
|
}}>
|
||||||
|
<label>
|
||||||
|
New todo:{' '}
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={newTodoText}
|
||||||
|
onChange={(e) => setNewTodoText(e.target.value)}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</form>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue