#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.