React Typescript createContext 类型问题

use*_*981 4 javascript typescript reactjs react-hooks

我正在尝试使用 React Context 钩子和打字稿来传递todos(初始状态)和addNewTodo(方法)。我尝试了多种解决方案,但没有成功,仍然出现错误。

PartialCannot invoke an object which is possibly 'undefined'泛型不会给上下文组件带来问题,但它在调用待办事项表单组件时给我带来错误addNewTodo。同样,未定义和空对象 {} 也会给出不同的错误。不知道如何解决它。如果我通过了any,那么 IntelliSense 将无法工作。

这是我的代码

待办事项上下文

import React, { useState, createContext, FC, useContext } from "react"

type Props = {
  children: React.ReactNode,
}

interface TaskContextProps {
  todos: Todo[],
  addNewTodo: addNewTodo
}

const initialTodos: Array<Todo> = [
  { id: 1, text: 'buy some milk', completed: false },
  { id: 2, text: 'go to gym', completed: false }
]

export const TaskListContext = createContext<Partial<TaskContextProps>>({})
// export const TaskListContext = createContext<TaskContextProps>({})
// export const TaskListContext = createContext<TaskContextProps | undefined>(undefined)

const TaskListContextProvider: FC<Props> = ({ children }) => {
  const [todos, setTodos] = useState(initialTodos)

  const addNewTodo: addNewTodo = (newTodo) => {
    setTodos([newTodo, ...todos])
  }

  return (
    <TaskListContext.Provider value={{ todos, addNewTodo }}>
      {children}
    </TaskListContext.Provider>
  )
}
Run Code Online (Sandbox Code Playgroud)

都都形式

import React, { useState, ChangeEvent, FormEvent, useContext } from 'react';

// import { useTaskList, TaskListContext } from '../context/TaskListContext';
import { TaskListContext } from '../context/TaskListContext';


const TodoForm = () => {
  const [newTodo, setNewTodo] = useState('')
  // const { addNewTodo } = useTaskList()
  const { addNewTodo } = useContext(TaskListContext)

  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
    setNewTodo(e.target.value)
  }

  const handleSubmit = (e: FormEvent<HTMLButtonElement>) => {
    e.preventDefault()
    const addTodo = { id: Math.random(), text: newTodo, completed: false }
    if (newTodo.trim()) {
      addNewTodo(addTodo)
    }
    else {
      alert('Todo can\'t be empty')
    }
    setNewTodo('')
  }

  return (
    <form>
      <input placeholder='your todo...' value={newTodo} onChange={handleChange} />
      <button onClick={handleSubmit}>Submit</button>
    </form>
  )
}
Run Code Online (Sandbox Code Playgroud)

我们将不胜感激您的帮助。

Alv*_*aro 6

为了防止 TypeScript 告诉我们对象的属性未定义,我们需要定义它们(使用 Partial 将每个属性设置为可能未定义,这是我们想要避免的)。

这意味着我们在定义上下文时需要为每个属性传递一些值:

export const TaskListContext = createContext<TaskContextProps>({
    todos: [],
    addNewTodo: () => {}
});
Run Code Online (Sandbox Code Playgroud)

一旦 Provider 初始化,该上下文初始值就会被替换,因此永远不会从组件中读取它们。

这样todosaddNewTodo总会有一个值,并且 TypeScript 不会抱怨。