mirror of
https://github.com/seigler/presentation-react-state-management
synced 2025-07-26 17:26: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
|
||||
|
||||
`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-dom": "^18.0.6",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"localforage": "^1.10.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router": "^6.4.2",
|
||||
"react-router-dom": "^6.4.2",
|
||||
|
@ -2003,6 +2004,11 @@
|
|||
"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": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
|
@ -2054,6 +2060,14 @@
|
|||
"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": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.16.0.tgz",
|
||||
|
@ -2288,6 +2302,14 @@
|
|||
"integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==",
|
||||
"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": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
|
@ -4155,6 +4177,11 @@
|
|||
"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": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
|
||||
|
@ -4194,6 +4221,14 @@
|
|||
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
||||
"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": {
|
||||
"version": "1.16.0",
|
||||
"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": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
|
|
|
@ -8,8 +8,9 @@
|
|||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "parcel",
|
||||
"build": "parcel build",
|
||||
"deploy": "git-directory-deploy --directory dist/",
|
||||
"clean": "rm -rf ./dist ./.cache ./.parcel-cache"
|
||||
"deploy": "echo > ./dist/.nojekyll && git-directory-deploy --directory dist/",
|
||||
"clean": "rm -rf ./dist",
|
||||
"publish": "npm run clean && npm run build && npm run deploy"
|
||||
},
|
||||
"keywords": [
|
||||
"presentation",
|
||||
|
@ -24,6 +25,7 @@
|
|||
"@types/react": "^18.0.21",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"localforage": "^1.10.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router": "^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 ReactDOM from 'react-dom'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { createBrowserRouter, RouterProvider } from 'react-router-dom'
|
||||
import { ErrorPage } from './error-page'
|
||||
import { Root } from './routes/root'
|
||||
import { App } from './App'
|
||||
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
path: '/',
|
||||
element: <Root />,
|
||||
path: '/*',
|
||||
element: <App />,
|
||||
errorElement: <ErrorPage />
|
||||
}
|
||||
])
|
||||
|
||||
const appEntry = document.getElementById('app')
|
||||
ReactDOM.render(
|
||||
const root = createRoot(appEntry!)
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<RouterProvider router={router} />
|
||||
</React.StrictMode>,
|
||||
appEntry
|
||||
</React.StrictMode>
|
||||
)
|
||||
|
|
|
@ -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