我试图建立一个自定义钩子,获取数据,对数据进行一些操作,并在react d3应用程序中返回被操纵的数据。数据type
interface EventViewerDataTypes {
date: string
site: string
type: string
value: string
}[]
在useEffect
钩子里面有一个错误Object is of type 'unknown'.
import { useState, useEffect } from "react"
import { json, timeParse } from "d3"
const parseTime = timeParse("%d-%m-%Y")
interface EventViewerDataTypes {
date: string
site: string
type: string
value: string
}[]
export const useData = (jsonUrl: string) => {
const [data, setData] = useState<EventViewerDataTypes | null>(null)
useEffect(() => {
json(jsonUrl).then((data) => {
data.forEach((d) => {
d.date = parseTime(d.date)
d.value = +d.value
})
setData(data)
})
}, [])
return data
}
我有点纠结于typescript
和任何帮助,或建议将是有价值的。
在Robby Cornelissen
的帮助下,我取得了一些进展并更新了代码,但仍然存在一些问题。所以我尝试将EventViewerDataTypes
更新为
interface EventViewerDataTypes {
date: string | Date | null
site: string
type: string
value: string | number
}[]
但仍有一些错误
json<EventViewerDataTypes[]>(jsonUrl).then((data) => {
data?.forEach((d) => {
// Error!
d.date = parseTime(d.date)
// Argument of type 'string | Date | null' is not assignable to parameter of type 'string'. Type 'null' is not assignable to type 'string'
d.value = +d.value
})
// Error!
//Argument of type 'EventViewerDataTypes[] | undefined' is not assignable to parameter of type 'SetStateAction<EventViewerDataTypes | null>'
setData(data)
})
你的代码有很多问题:
无类型JSON响应
TypeScript编译器无法推断出将从jsonUrl
中检索到什么类型。
根据类型定义,json()
函数有一个泛型约束,允许您指定预期的返回类型,因此这应该修复它:
json<EventViewerDataTypes>(jsonUrl).then((data) => {
/* ... */
});
undefined
JSON响应的处理
由于从类型定义来看,json()
函数似乎也可以返回undefined
,因此您可能还需要在循环data
之前使用可选的链接操作符(或if
检查):
data?.forEach((d) => {
/* ... */
});
如果你之后调用的setData(data)
函数不接受undefined
,你可能最好使用显式的if
检查,要么调用setData(null)
,要么根本不调用setData()
。
JSON类型与模型类型差异
在您检索的JSON数据和您希望在应用程序中对其建模的方式之间存在差异。首先,输入单个EventViewerDataType
对象(而不是EventViewerDataTypes
),然后在需要数组时使用EventViewerDataType[]
,这样更具可读性和便利性。
根据你的处理逻辑,我认为EventViewerDataType
应该是这样输入的:
interface EventViewerDataType {
date: Date | null;
site: string;
type: string;
value: number;
}
然后,由于JSON似乎只包含字符串,我将使用映射类型来定义数据传输对象:
type StringValues<T> = {
[K in keyof T]: string;
}
然后,在您的处理逻辑中,而不是使用forEach()
,使用map()
从JSON格式对象(StringValues<EventViewerDataType>[]
)映射到您的模型对象(EventViewerDataType[]
)。