Свойство ‘toDos’ не существует для типа TS2339

#typescript #react-hooks #reducers #react-tsx

#typescript #реагирующие перехваты #редукторы #реагировать-tsx

Вопрос:

Я новичок, впервые изучающий ts. Заранее благодарим вас за то, что поделились своими знаниями. Я создаю список задач. Я использовал react для его завершения. Но теперь я использую react и typescript вместе для завершения кода.

Мне кажется, что ‘reducer’ не работает должным образом. Как я могу управлять этим? Я был бы признателен, если бы вы дали мне знать. Это код ‘App.tsx’ с поверхностной ошибкой.

 import React, { useState } from "react";
import Add from "./Add";
import List from "./List";
import ToDo from "./ToDo";
import Title from "./Title";
import Progress from "./Progress";
import styled from "styled-components";

interface ITodo {
  toDos: string;
  completed: boolean;
}

function App() {
  const { toDos, completed } = useState<ITodo>(); 👈 Error part
  return (
    <Title>
      <Add />
      <Progress />
      <Lists>
        <List title={toDos.length !== 0 ? "To Dos" : ""}>
          {toDos.map((toDo: any) => (
            <ToDo key={toDo.id} id={toDo.id} text={toDo.text} isCompleted={false} />
          ))}
        </List>
        <List title={completed.length !== 0 ? "Completed" : ""}>
          {completed.map((toDo: any) => (
            <ToDo key={toDo.id} id={toDo.id} text
              {...toDo.text} isCompleted />
          ))}
        </List>
      </Lists>
    </Title>
  );
}

export default App;
 

Этот код является кодом ‘reducer.tsx’, в котором, как я думал, была проблема.

 import { v4 as uuidv4 } from "uuid";
import { ADD, DEL, COMPLETE, UNCOMPLETE, EDIT } from "./actions";

export const initialState = {
  toDos: [],
  completed: [],
};

const reducer = ({ state, action }: any) => {
  switch (action) {
    case ADD:
      return {
        ...state,
        toDos: [...state.toDos, { text: action.payload, id: uuidv4() }],
      };
    case DEL:
      return {
        ...state,
        toDos: state.toDos.filter((toDo: { id: number; }) => toDo.id !== action.payload),
      };
    case COMPLETE:
      const target = state.toDos.find((toDo: { id: number; }) => toDo.id === action.payload);
      return {
        ...state,
        toDos: state.toDos.filter((toDo: { id: number; }) => toDo.id !== action.payload),
        completed: [...state.completed, { ...target }],
      };
    case UNCOMPLETE:
      const aTarget = state.completed.find(
        (toDo: { id: any; }) => toDo.id === action.payload
      );
      return {
        ...state,
        toDos: [...state.toDos, { ...aTarget }],
        completed: state.completed.filter(
          (complete: { id: number; }) => complete.id !== action.payload
        ),
      };
    case EDIT:
      const bTarget = state.toDos.find((toDo: { id: number; }) => toDo.id === action.id);
      const rest = state.toDos.filter((toDo: { id: number; }) => toDo.id !== action.id);
      return {
        ...state,
        toDos: rest.concat({ ...bTarget, text: action.payload }),
      };
    default:
      return;
  }
};

export default reducer;
 

Этот код является кодом ‘context.tsx’.

 import React, { createContext, useReducer, useContext } from 'react';
import reducer, { initialState } from "./reducer";

export type Todo = {
  id: number;
  text: string;
  done: boolean;
};

export type TodosState = Todo[];

const ToDosContext = createContext<TodosState | any>(undefined);

const ToDosProvider = ({ children }: { children: React.ReactNode }) => {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <ToDosContext.Provider value={{ state, dispatch }}>
      {children}
    </ToDosContext.Provider>
  );
};

export const useDispatch = () => {
  const { dispatch } = useContext(ToDosContext);
  return dispatch;
};

export const useState = () => {
  const { state } = useContext(ToDosContext);
  return state;
};

export default ToDosProvider;
 

Ответ №1:

То, что здесь происходит, связано с путаницей именования. Вы создали пользовательский хук useState , имя которого совпадает со встроенным хуком React, и вы используете неправильный.

Здесь появляется ошибка:

 const { toDos, completed } = useState<ITodo>(); 👈 Error part
 

Из-за этого:

 import React, { useState } from "react";
 

Вы хотели использовать свой пользовательский useState хук, который возвращает объект со свойствами toDos и completed . Но вместо импорта этого перехвата вы импортировали встроенный перехват React useState , который возвращает массив с двумя записями ( state и setState ).

Перейдите context.tsx и переименуйте свои пользовательские хуки во что-то менее двусмысленное, например useTodosState , и useTodosDispatch . Это не является строго обязательным, но это сделает жизнь намного проще!

Затем перейдите в App.tsx и замените useState на useTodosState , убедившись, что импортировали его из context.tsx . Теперь, когда нет сомнений в том, какой хук вы намеревались использовать, вам не нужно беспокоиться об автоматическом импорте IDE useState из React.

Комментарии:

1. Я решил эту проблему благодаря вам. Но появилась другая проблема. Можете ли вы сказать мне это? Спасибо за вашу тяжелую работу. Ошибка типа: невозможно уничтожить свойство ‘toDos’ для ‘Object(…) (…)’, поскольку оно не определено. const { toDos, completed } = useTodosState(); Это все еще проблема.

2. Похоже, вы не можете находиться внутри ToDosProvider. Убедитесь, что вы обернули весь компонент приложения в ToDosProvider.