start useState

This commit is contained in:
Joshua Seigler 2022-10-09 21:28:54 -04:00
parent 98ab1bce45
commit 2a4cd44504
8 changed files with 168 additions and 18 deletions

View file

@ -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
View file

@ -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",

View file

@ -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
View 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>
)
}

View file

@ -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>
)

View file

@ -1,5 +0,0 @@
import React from 'react'
export function Root() {
return <h1>React State Management</h1>
}

3
src/strategies/index.ts Normal file
View file

@ -0,0 +1,3 @@
import { UseState } from "./useState";
export const strategies = [{ name: 'useState', component: UseState }]

View 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>
)
}