react中reducer+上下文实战

发布于:2024-06-03 ⋅ 阅读:(135) ⋅ 点赞:(0)

APP.js文件

import { useReducer, createContext, useContext } from "react"
import AddTask from "./components/AddTask"
import TaskList from "./components/TaskList"

const initialTasks = [
  { id: 0, text: 'Visit Kafka Museum', done: true },
  { id: 1, text: 'Watch a puppet show', done: false },
  { id: 2, text: 'Lennon Wall pic', done: false }
]
function tasksReducer(tasks, action) {
  switch (action.type) {
    case "added":
      return [...tasks, {
        id: action.id,
        text: action.text,
        done: false
      }]
    case "changed":
      return tasks.map(t => {
        if (t.id === action.task.id) {
          // return action.task
          return {...action.task, done: !action.task.done}
        } else {
          return t
        }
      })
    case "saved":
      return tasks.map(t => {
        if (t.id === action.id) {
          return {...t, text: action.text}
        } else {
          return t
        }
      })
    case "deleted":
      return tasks.filter(t => t.id !== action.id)
    default:
      // 主动抛出异常
      throw Error("Unknown action" + action.type)
  }
}

const TaskContext = createContext(null)
export function useTasks() {
  return useContext(TaskContext)
}
const TaskDispatchContext = createContext(null)
export function useTasksDispatch() {
  return useContext(TaskDispatchContext)
}

function App() {
  // useReducer Hooks函数:用于管理组件的状态和状态更新
  const [tasks, dispatch] = useReducer(tasksReducer, initialTasks)

  return (
    <>
      <TaskContext.Provider value={tasks}>
        <TaskDispatchContext.Provider value={dispatch}>
          <h1>Prague itinerary</h1>
          <AddTask />
          <TaskList />
        </TaskDispatchContext.Provider>
      </TaskContext.Provider>
    </>
  )
}

export default App

AddTask.js

import { useState } from "react"
import { useTasksDispatch } from "../App" 

export default function AddTask() {
    const [text, setText] = useState("")
    const dispatch = useTasksDispatch()

    return (
        <>
            <input value={text} placeholder="Add task" onChange={e => {
                setText(e.target.value)
            }}></input>
            <button onClick={() => {
                // onAddTask(text)
                dispatch({
                    type: "added",
                    id: Date.now(),
                    text: text
                })
                setText("")
            }}>Add</button>
        </>
    )
}

TaskList.js

import { useState } from "react"
import { useTasks, useTasksDispatch } from "../App"

export default function TaskList() {
    const tasks = useTasks()

    return (
        <ul>
            {tasks.map(t => ( 
                <li key={t.id}>
                    <Item t={t} />
                </li>
            ))}
        </ul>
    )
}

function Item({ t }) {
    const [text, setText] = useState("")
    const [status, setStatus] = useState(0)

    const dispatch = useTasksDispatch()

    return (
        <>
            <input
            checked={t.done}
            onChange={e => {
                dispatch({
                    type: "changed",
                    task: {...t, done: !e.target.checked}
                })
            }}
            type="checkbox" />

            {!status ?
                <>
                    {t.text} {" "}
                    <button onClick={e => {
                        setStatus(!status)
                        setText(t.text)
                    }}>Edit</button>
                </>
             : 
                <>
                    <input value={text} onChange={e => {
                        setText(e.target.value)
                    }} /> {" "}
                    <button onClick={e => {
                        setStatus(!status)
                        // onSaveTask(text, t.id)
                        dispatch({
                            type: "saved",
                            text: text,
                            id: t.id
                        })
                    }}>Save</button>
                </>
             }
            
            <button onClick={e => {
                dispatch({
                    type: "deleted",
                    id: t.id
                })
            }}>delete</button>
        </>
    )
}


网站公告

今日签到

点亮在社区的每一天
去签到