zheng 2 周之前
父节点
当前提交
ac08b7c5c6

+ 166 - 0
21.react/高阶/project2/src/App.tsx

@@ -0,0 +1,166 @@
+import { useState, useRef } from 'react'
+import './App.css'
+
+interface Todo {
+    id: number,
+    text: string,
+    completed: boolean
+}
+
+type Filter = 'all' | 'active' | 'completed';
+
+function filterTodos(todos: Todo[], filter: Filter): Todo[] {
+    switch (filter) {
+        case 'all':
+            return todos;
+        case 'active':
+            return todos.filter(todo => !todo.completed);
+        case 'completed':
+            return todos.filter(todo => todo.completed);
+        default:
+            return todos;
+    }
+}
+function Header({ addTodo }: { addTodo: (text: string) => void }) {
+    const inpRef = useRef<HTMLInputElement>(null);
+    const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
+        if (e.keyCode === 13) {
+            addTodo(inpRef.current!.value);
+            inpRef.current!.value = ""
+        }
+    }
+    return (
+        <div>
+            <header className="header">
+                <h1>todos</h1>
+                <input
+                    ref={inpRef}
+                    autoFocus
+                    autoComplete="off"
+                    placeholder="输入您要完成的任务?"
+                    className="new-todo"
+                    onKeyDown={handleKeyDown}
+                />
+            </header>
+        </div>
+    )
+}
+
+function Main({ onToggleAll, allCompleted }: { onToggleAll: (val: boolean) => void, allCompleted: boolean }) {
+    const handleToggle = () => {
+        allCompleted = !allCompleted;
+        onToggleAll(allCompleted)
+    }
+    return (
+        <div>
+            <input id="toggle-all" type="checkbox" className="toggle-all" onChange={handleToggle} checked={allCompleted} />
+            <label htmlFor="toggle-all"></label>
+        </div>
+    )
+}
+
+function TodoItem({ todo, onDelete, onActive }: { todo: Todo, onDelete: (id: number) => void, onActive: (id: number) => void }) {
+
+    const deleteTodo = (val: number) => {
+        onDelete(val)
+    }
+    const activeTodo = (val: number) => {
+        onActive(val)
+    }
+    return (
+        <li className={todo.completed ? 'completed' : ''}>
+            <div className="view">
+                <input type="checkbox" className="toggle" checked={todo.completed} onChange={() => activeTodo(todo.id)} />
+                <label>{todo.text}</label>
+                <button className="destroy" onClick={() => deleteTodo(todo.id)}></button>
+            </div>
+            <input type="text" className="edit" />
+        </li>
+    )
+}
+
+function Footer({ count, clearAll, filter, tabFilter }: { count: number, clearAll: () => void, filter: Filter, tabFilter: (val: string) => void }) {
+    console.log(filter, 'filter')
+    return (
+        <div>
+            <span className="todo-count"><strong>{count}</strong> items left </span>
+            <ul className="filters">
+                <li><a href="#/all" onClick={() => tabFilter('all')} className={filter == 'all' ? 'selected' : ''}>All</a></li>
+                <li><a href="#/active" onClick={() => tabFilter('active')} className={filter === 'active' ? 'selected' : ''}>Active</a></li>
+                <li><a href="#/completed" onClick={() => tabFilter('completed')} className={filter === 'completed' ? 'selected' : ''}>Completed</a></li>
+            </ul>
+            <button className="clear-completed" onClick={clearAll}>Clear completed</button>
+        </div>
+    )
+}
+
+function App() {
+    const [todos, setTodos] = useState<Todo[]>([
+        {
+            id: 1, text: '吃饭', completed: false
+        },
+        {
+            id: 2, text: '睡觉', completed: false
+        },
+        {
+            id: 3, text: '打豆豆', completed: true
+        }
+    ])
+    const completeCount = todos.filter((item) => !item.completed).length;
+    const isCompleted = todos.every((item) => item.completed);
+    const [isFilter, setIsFilter] = useState<Filter>('all');
+    const newArr = filterTodos(todos, isFilter);
+    const handleAdd = (val: string) => {
+        setTodos([...todos, {
+            id: Date.now(),
+            text: val,
+            completed: false
+        }])
+    }
+    const handleDelete = (val: number) => {
+        setTodos((prevTodos) => { return prevTodos.filter((todo) => todo.id !== val) })
+    }
+    const handleAvtive = (val: number) => {
+        setTodos((prevTodos) => prevTodos.map((todo) => {
+            return todo.id === val ? { ...todo, completed: !todo.completed } : todo
+        }))
+    }
+    const handleAll = (val: boolean) => {
+        setTodos((prev) => prev.map((todo) => {
+            return { ...todo, completed: val }
+        }))
+    }
+    const handleClear = () => {
+        setTodos([...todos.filter((todo) => !todo.completed)])
+    }
+    const handleSet = (val: Filter) => {
+        setIsFilter(val)
+    }
+    return (
+        <>
+            <div id="app">
+                <section className="todoapp">
+                    <Header addTodo={handleAdd}></Header>
+                    <section className="main">
+                        <Main onToggleAll={handleAll} allCompleted={isCompleted}></Main>
+                        <ul className="todo-list">
+                            {
+                                newArr.map((todo) => {
+                                    return (
+                                        <TodoItem key={todo.id} todo={todo} onDelete={handleDelete} onActive={handleAvtive}></TodoItem>
+                                    )
+                                })
+                            }
+                        </ul>
+                    </section>
+                    <footer className="footer">
+                        <Footer count={completeCount} clearAll={handleClear} filter={isFilter} tabFilter={handleSet}></Footer>
+                    </footer>
+                </section>
+            </div>
+
+        </>
+    )
+}
+
+export default App

+ 3 - 1
21.react/高阶/project3/src/App.jsx

@@ -10,6 +10,8 @@ import UseLearnRef from './components/UseLearnRef'
 import UseLearnImperativeHandle from './components/UseLearnImperativeHandle'
 import Use from './components/Use'
 import UseLearnOptimistic from './components/UseLearnOptimistic'
+import UseLearnFormStatus from './components/UseLearnFormStatus'
+import UseLearnActionState from './components/UseLearnActionState'
 import { useState } from 'react'
 
 
@@ -18,7 +20,7 @@ function App() {
   return (
     <>
       <h1>首页</h1>
-      <UseLearnOptimistic />
+      <UseLearnImperativeHandle />
       {/* <UseLearnMemo /> */}
       {/* {isShow ? <UseLearnEffect /> : '无内容'} */}
       {/* {isShow ? <UseDemo /> : '无内容'} */}

+ 56 - 0
21.react/高阶/project3/src/components/UseLearnActionState.jsx

@@ -0,0 +1,56 @@
+import { useActionState, useState } from "react";
+import { useFormStatus } from 'react-dom';
+
+
+const api = {
+    async delWay(ids) {
+        await new Promise((resolve, reject) => {
+            setTimeout(() => {
+                Math.random() > 0.1 ? resolve() : reject()
+            }, 3000)
+        })
+    }
+}
+
+async function loginInfo(prev, formData) {
+    const userName = formData.get("username");
+    const passWord = formData.get('password')
+    await api.delWay(userName, passWord)
+}
+function UseLearnActionState() {
+    // const [loading, setLoading] = useState(false);
+    // const [error, setError] = useState('');
+    // const [success, setSuccess] = useState('');
+    // const [data, setData] = useState(null);
+    // async function handleAction() {
+    //     setLoading(true);
+    //     setError("")
+    //     const res = await AudioParam.delWay(12);
+    //     setData(res);
+    //     setLoading(false)
+    // }
+    // return (
+    //     <div>
+    //         <h1>useActionState</h1>
+    //         <form action="handleAction">
+    //             <SubmitButton></SubmitButton>
+    //         </form>
+    //     </div>
+    // )
+    const [state, handleAction, isPending] = useActionState(loginInfo, {})
+    console.log(state, isPending, '答应')
+    return (
+        <form action={handleAction}>
+            用户名:<input type="text" name='username' />
+            <br /><br />
+            密码:<input type="password" name='password' />
+            <br /><br />
+            <button>å
+                {isPending ? '正在登录' : '登录'}
+            </button>
+        </form>
+    )
+
+}
+
+export default UseLearnActionState;

+ 1 - 1
21.react/高阶/project3/src/components/UseLearnContext.jsx

@@ -24,7 +24,7 @@ function UseLearnContext() {
     )
 }
 
-// 接受组件 Context 
+// 接受组件 Context 消费者
 function Main() {
     const { user, setUser } = useContext(UserContext);
     const { theme, setTheme } = useContext(ThemeContext);

+ 77 - 0
21.react/高阶/project3/src/components/UseLearnFormStatus.jsx

@@ -0,0 +1,77 @@
+import { useState } from "react";
+import { useFormStatus } from 'react-dom';
+
+const api = {
+    async delWay(ids) {
+        await new Promise((resolve, reject) => {
+            setTimeout(() => {
+                Math.random() > 0.1 ? resolve() : reject()
+            }, 3000)
+        })
+    }
+}
+function SubmitButton() {
+    const { pending, data } = useFormStatus();
+    console.log(pending, 'pending', data)
+    return (
+        <div>
+            <button disabled={pending}>
+                {pending ? '正在加载' : '正常提交'}
+            </button>
+        </div>
+    )
+}
+
+function UseLearnFormStatus() {
+    const [names, setNames] = useState("图图")
+    // const [loading, setLoading] = useState(false)
+    async function handleSubmit(e) {
+        // e.preventDefault();
+        // // setLoading(true)
+        // setTimeout(() => {
+        //     console.log("提交", name)
+        //     // setLoading(false)
+        // }, 3000)
+        // const name1 = formData.get('names');
+        // console.log("执行")
+        const res = await api.delWay(names);
+        console.log(res, 'res')
+        // setTimeout(() => {
+        //     console.log("提交", names)
+        // }, 3000)
+    }
+    return <div>
+        {/* 
+            必须使用在form表单中
+            必须使用在action上
+            必须
+        */}
+        <h1>useFormStatus</h1>
+        <form action={handleSubmit}>
+            <input type="text" value={names} /><br />
+            {/* <button onClick={handleSubmit}> 展示</button> */}
+            <SubmitButton></SubmitButton>
+        </form>
+    </div>
+
+
+
+    // return loading ? (
+    //     <div>
+    //         加载中
+    //     </div>
+    // ) : (
+    //     <div>
+
+    //         <h1>useFormStatus</h1>
+    //         <form action="" onSubmit={handleSubmit}>
+    //             <input type="text" value={name} /><br />
+    //             {/* <button onClick={handleSubmit}> 展示</button> */}
+    //             <SubmitButton></SubmitButton>
+    //         </form>
+    //     </div>
+    // )
+
+}
+
+export default UseLearnFormStatus;