我对开发很陌生,需要一些帮助和耐心。我正在将一个React项目转换为TypeScript,在管理和更新Context组件内的状态时遇到了一些问题。
我正在构建一个日志查看器,根据选择的任务显示一系列任务及其嵌套的子任务。
事件在Event类中定义,该类由自定义useFetch钩子中的数据填充。这些作为对象存储在事件数组中。选择任务时,该任务存储在当前的"selectedTask"状态,并且还必须推送到"Hierarchy"数组中。
其想法是当用户单击任务日志的多个嵌套层时,显示随后选择的任务的层次结构。
这些事件在类型"ContextObject"中定义如下:
hierarchy: Event[] | undefined
setHierarchy: Dispatch<SetStateAction<Event[] | undefined>>
selectedSubEvent: Event[];
setSelectedSubEvent: Dispatch<SetStateAction<Event[]>>;
它们通过useState:进行管理
const [hierarchy, setHierarchy] = useState<Event[] | undefined>([]);
const [selectedSubEvent, setSelectedSubEvent] = useState<Event[]>([]);
为了用所选任务更新层次结构,我在useEffect中使用了一个状态更新函数,如下所示,并在"。。。prevState':
useEffect(() => {
setHierarchy((prevState) => [...prevState, selectedSubEvent])
}, [selectedSubEvent]);
我得到的错误:
Type 'Event[] | undefined' is not an array type.ts(2461)
(parameter) prevState: Event[] | undefined
当我放弃useEffect中的状态更新函数,只将"Hierarchy"设置为"selectedEvent"时,它确实将单个事件设置为层次结构,但显然我需要更多。
我也试过在传播之前检查prevState,但这会出现多个错误:
setHierarchy((prevState) =>
prevState ? [...prevState, selectedSubEvent] : [selectedSubEvent]
);
//Errors
Argument of type '(prevState: Event[] | undefined) => (Event | Event[])[]' is not assignable to parameter of type 'SetStateAction<Event[] | undefined>'.
Type '(prevState: Event[] | undefined) => (Event | Event[])[]' is not assignable to type '(prevState: Event[] | undefined) => Event[] | undefined'.
Type '(Event | Event[])[]' is not assignable to type 'Event[]'.
Type 'Event | Event[]' is not assignable to type 'Event'.
Type 'Event[]' is missing the following properties from type 'Event': key, id, startTime, endTime, and 3 more.ts(2345)
我意识到我没有提供太多我尝试过的东西,但我尝试过无数的文章、教程以及React和TypeScript文档,我不知所措🤷♂️
如果我能提供更多信息,请告诉我。如果有人能给我指明正确的方向,我很乐意继续挖掘。
更新
我尝试了@Leigh.D提供的建议,得到了以下结果。
首先:删除"未定义"会导致以下错误:
Argument of type '(prevState: Event[]) => (Event | Event[])[]' is not assignable to parameter of type 'SetStateAction<Event[]>'.
Type '(prevState: Event[]) => (Event | Event[])[]' is not assignable to type '(prevState: Event[]) => Event[]'.
Type '(Event | Event[])[]' is not assignable to type 'Event[]'.
Type 'Event | Event[]' is not assignable to type 'Event'.
Type 'Event[]' is missing the following properties from type 'Event': key, id, startTime, endTime, and 3 more.ts(2345)
(parameter) prevState: Event[]
第二:这也会导致我的上下文提供程序值中的setHierarchy属性出错,但当我从上下文对象中的sethierary中删除"undefined"时,如下所示:
setHierarchy: Dispatch<SetStateAction<Event[]>>
这个错误消失了:
Type 'Dispatch<SetStateAction<Event[]>>' is not assignable to type 'Dispatch<SetStateAction<Event[] | undefined>>'.
Type 'SetStateAction<Event[] | undefined>' is not assignable to type 'SetStateAction<Event[]>'.
Type 'undefined' is not assignable to type 'SetStateAction<Event[]>'.ts(2322)
sub-event-context.tsx(20, 2): The expected type comes from property 'setHierarchy' which is declared here on type 'SubEventContextObject'
(property) setHierarchy: React.Dispatch<React.SetStateAction<Event[] | undefined>>
第三:当我根据FIRST组合删除"未定义"并检查"prevState"时,我得到以下信息:
Argument of type '(prevState: Event[]) => (Event | Event[])[]' is not assignable to parameter of type 'SetStateAction<Event[]>'.
Type '(prevState: Event[]) => (Event | Event[])[]' is not assignable to type '(prevState: Event[]) => Event[]'.
Type '(Event | Event[])[]' is not assignable to type 'Event[]'.
Type 'Event | Event[]' is not assignable to type 'Event'.
Type 'Event[]' is missing the following properties from type 'Event': key, id, startTime, endTime, and 3 more.ts(2345)
(parameter) prevState: Event[]
第四:当我删除选中的"prevState"并对其进行类型转换时,VSCode/Prettier会将其包装在括号中——我不知道这是否是正常行为?
useEffect(() => {
setHierarchy((prevState) => [
...(prevState as Event[]),
selectedSubEvent,
]);
}, [selectedSubEvent]);
除此之外,我也犯了和第三次一样的错误。
解决方案
感谢Leigh.D和Daniel Baldi帮助我解决了这个问题。我似乎有两个问题,他们的两个答案共同纠正了我的错误。任何想要解决类似问题的人,请务必阅读两个答案。
我将Daniel的解决方案标记为公认的答案,主要是因为在我缺乏经验的看来,这是一个更复杂的问题。如果我的想法不正确,请纠正我。
再次感谢您提供的帮助。我真的很感激!
Deon
问题在于您的类型定义(特别是未定义的(以及排列运算符如何解释它。
const [hierarchy, setHierarchy] = useState<Event[] | undefined>([]);
您可以从类型中删除未定义的(因为您无论如何都将状态默认为空数组(,在设置状态或typecast prevState时执行检查,以便排列运算符知道它是一个数组(不是最佳选项(,即:
setHierarchy((prevState) => prevState? [...prevState, selectedSubEvent] : [selectedSubEvent])
setHierarchy((prevState) => [...prevState as Event[], selectedSubEvent])
好吧,我想我已经弄清楚了这里发生了什么。让我们首先考虑一下这里发生了什么:
setHierarchy((prevState) =>
prevState ? [...prevState, selectedSubEvent] : [selectedSubEvent]
);
正如您在ContextObject
接口中所述,selectedSubEvent
是Event
的数组,而prevState
具有相同类型的hierarchy
,因此是Event
或未定义的数组。
因此,查看代码,如果prevState
的计算结果为truthy值,则创建此[...prevState, selectedSubEvent]
,它包含prevState
的排列,从而产生Event
和selectedSubEvent
,从而产生事件的数组。这是第一个问题,因为得到的值最终是(Event | Event[])[]
类型,而它应该是Event[]
类型。
当prevState
为falsy时,您将hierarchy
设置为[selectedSubEvent]
。这将创建事件(Event[][]
(的数组。这是第二个问题!
我可能在这里做错了什么,因为在没有实际运行的情况下尝试编写代码是非常棘手的,但我想尝试一下,它应该会正常工作:
setHierarchy((prevState) =>
prevState ? [...prevState, ...selectedSubEvent] : selectedSubEvent
);