Skip to content

Commit

Permalink
more react 19 hooks examples for chap5
Browse files Browse the repository at this point in the history
  • Loading branch information
jsoneaday committed Sep 20, 2024
1 parent 6d4903b commit b7a1347
Show file tree
Hide file tree
Showing 7 changed files with 255 additions and 131 deletions.
203 changes: 86 additions & 117 deletions Chap5/components/package-lock.json

Large diffs are not rendered by default.

12 changes: 8 additions & 4 deletions Chap5/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
"preview": "vite preview"
},
"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
"@types/react": "npm:types-react@rc",
"@types/react-dom": "npm:types-react-dom@rc",
"react": "19.0.0-rc-5dcb0097-20240918",
"react-dom": "19.0.0-rc-5dcb0097-20240918"
},
"devDependencies": {
"@eslint/js": "^9.9.0",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@vitejs/plugin-react-swc": "^3.5.0",
"eslint": "^9.9.0",
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
Expand All @@ -25,5 +25,9 @@
"typescript": "^5.5.3",
"typescript-eslint": "^8.0.1",
"vite": "^5.4.1"
},
"overrides": {
"@types/react": "npm:types-react@rc",
"@types/react-dom": "npm:types-react-dom@rc"
}
}
22 changes: 12 additions & 10 deletions Chap5/components/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,31 @@
import { ChangeEvent, useEffect, useState } from "react";
import "./App.css";
import Home, { UserType } from "./Home";
import DeferredValue from "./DeferredValue";
import Transitioner from "./Transitioner";

async function fetchData(url: string) {
const response = await fetch(url);
const users = await response.json();
return (Array.isArray(users) ? users : [users]) as UserType[];
}

function App() {
const [id, setId] = useState("");
const [users, setUsers] = useState<UserType[]>([]);
const [usersPromise, setUsersPromise] = useState<Promise<UserType[]>>();

useEffect(() => {
const idToGet = `https://jsonplaceholder.typicode.com/posts/${id}`;
fetch(idToGet).then((result) => {
result.json().then((users) => {
console.log("users updated", users);
setUsers(Array.isArray(users) ? users : [users]);
});
});
}, [id, users]);
setUsersPromise(fetchData(idToGet));
}, [id]);

const onChange = (e: ChangeEvent<HTMLInputElement>) => {
setId(e.target.value);
};

return (
<>
id: <input type="text" value={id} onChange={onChange} />
<Home users={users} />
<Transitioner />
</>
);
}
Expand Down
15 changes: 15 additions & 0 deletions Chap5/components/src/Awaitable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Suspense } from "react";
import Fetcher from "./Fetcher";
import { UserType } from "./Home";

interface AwaitableProps {
fetchPromise?: Promise<UserType[]>;
}

export default function Awaitable({ fetchPromise }: AwaitableProps) {
return (
<Suspense fallback={<div>Loading users ...</div>}>
{fetchPromise ? <Fetcher fetchPromise={fetchPromise} /> : null}
</Suspense>
);
}
20 changes: 20 additions & 0 deletions Chap5/components/src/DeferredValue.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ChangeEvent, useDeferredValue, useState } from "react";

export default function DeferredValue() {
const [inputValue, setInputValue] = useState("");
const [greeting, setGreeting] = useState("hello");
const deferredGreeting = useDeferredValue(greeting);

const onChange = (e: ChangeEvent<HTMLInputElement>) => {
setTimeout(() => setGreeting(`Hi, ${e.target.value}`), 2000);

setInputValue(e.target.value);
};

return (
<div>
<input type="text" value={inputValue} onChange={onChange} />
<span>{deferredGreeting}</span>
</div>
);
}
31 changes: 31 additions & 0 deletions Chap5/components/src/Fetcher.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { use } from "react";
import { UserType } from "./Home";

interface FetcherProps {
fetchPromise: Promise<UserType[]>;
}

export default function Fetcher({ fetchPromise }: FetcherProps) {
const users = use(fetchPromise);

return (
<>
{users?.map((user) => {
return (
<div
key={user?.id}
style={{
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
marginBottom: "10px",
}}
>
<div>id: {user?.id}</div>
<div>title: {user?.title}</div>
</div>
);
})}
</>
);
}
83 changes: 83 additions & 0 deletions Chap5/components/src/Transitioner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { useState, useTransition, MouseEvent, useEffect } from "react";
import { UserType } from "./Home";

enum SelectedItem {
Default,
Users,
Message,
}

export default function Transitioner() {
const [selectedItem, setSelectedItem] = useState(SelectedItem.Default);
const [_isPending, startTransition] = useTransition();

const onClickUsers = (e: MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
startTransition(() => {
setSelectedItem(SelectedItem.Users);
});
};

const onClickMessage = (e: MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
startTransition(() => {
setSelectedItem(SelectedItem.Message);
});
};

return (
<div>
<div
style={{
display: "flex",
justifyContent: "space-between",
width: "400px",
}}
>
<button onClick={onClickUsers}>get users</button>

<button onClick={onClickMessage}>show message</button>
</div>
<div>
{selectedItem === SelectedItem.Default && <div>Start here</div>}{" "}
{selectedItem === SelectedItem.Users && <UsersLoader />}
{selectedItem === SelectedItem.Message && <ShowMessage />}
</div>
</div>
);
}

export function UsersLoader() {
const [users, setUsers] = useState<UserType[]>([]);

useEffect(() => {
const users = [];
for (let i = 0; i < 200; i++) {
users.push({
userId: i,
id: i,
title: "Title A",
body: "Body A",
});
}
setUsers(users);
}, []);

return (
<>
{users?.map((user) => (
<UserItem key={user.id} user={user} />
))}
</>
);
}

export function UserItem({ user }: { user: UserType }) {
const start = Date.now();
while (Date.now() - start < 10) {}
return <div>{user.title}</div>;
}

export function ShowMessage() {
return <div>Hello World!</div>;
}

0 comments on commit b7a1347

Please sign in to comment.