Проблема с типами createContext в React Typescript - PullRequest
2 голосов
/ 04 августа 2020

Я пытаюсь передать todos (начальное состояние) и addNewTodo (методы) с помощью перехватчика React Context и машинописного текста. Я пробовал несколько решений, но безуспешно, все еще получаю ошибки.

Partial дженерики не вызывают проблем с компонентом контекста, но дают мне ошибку Cannot invoke an object which is possibly 'undefined' при вызове addNewTodo в компоненте формы задачи . Точно так же неопределенные и пустые объекты {} также дают разные ошибки. Не могу понять, как это исправить. Если я передаю any, IntelliSense не будет работать.

Вот мой код

TodoContext

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

Todo Form

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

Мы будем благодарны за вашу помощь.

1 Ответ

2 голосов
/ 04 августа 2020

Чтобы TypeScript не сообщал, что свойства объекта не определены, нам нужно их определить (используя Partial устанавливает каждое свойство как возможное неопределенное, чего мы хотим избежать).

Это означает, что нам нужно передать некоторое значение для каждого свойства при определении контекста:

export const TaskListContext = createContext<TaskContextProps>({
    todos: [],
    addNewTodo: () => {}
});

Начальные значения этого контекста будут заменены, как только провайдер будет инициализирован, поэтому они никогда не будут считаны из Компонента.

Таким образом, todos и addNewTodo всегда будут иметь значение, и TypeScript не будет жаловаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...