简体   繁体   English

在反应 d3 中设置数据时,对象属于“未知”类型错误

[英]Object is of type 'unknown' error while setting data in react d3

I am trying to set up a custom hook that fetches data, does some manipulations on the data and returns the manipulated data in a react d3 application.我正在尝试设置一个自定义挂钩来获取数据,对数据进行一些操作并在 react d3 应用程序中返回操作后的数据。 The data type is数据type

interface EventViewerDataTypes {
    date: string
    site: string
    type: string
    value: string
}[]

Inside the useEffect hook there is an error Object is of type 'unknown'.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
}

I'm a bit struggling with typescript and any help, or recommendations would be valuable.我在typescript方面有点挣扎,任何帮助或建议都会很有价值。

Update更新

With the help of Robby Cornelissen , I made some progress and updated the code, and still some issues.Robby Cornelissen的帮助下,我取得了一些进展并更新了代码,但仍然存在一些问题。 So I tried updating the EventViewerDataTypes as所以我尝试将EventViewerDataTypes更新为

interface EventViewerDataTypes {
    date: string | Date | null
    site: string
    type: string
    value: string | number
}[]

But still have some errors但是还是有一些错误

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) 

})

There are a number of issues with your code:您的代码存在许多问题:

Untyped JSON response无类型的 JSON 响应

There is no way for the TypeScript compiler to infer what type will be retrieved from the jsonUrl . TypeScript 编译器无法推断将从jsonUrl检索到的类型。

According to the type definition , the json() function has a generic constraint that lets you specify the expected return type, so this should fix it:根据类型定义json()函数有一个通用约束,可让您指定预期的返回类型,因此应该修复它:

json<EventViewerDataTypes>(jsonUrl).then((data) => {
  /* ... */
});

Handling of an undefined JSON response处理undefined的 JSON 响应

Since from the type definition it seems that the json() function can also return undefined , you might also need to use the optional chaining operator (or an if -check) before looping over data :由于从类型定义看来json()函数也可以返回undefined ,因此您可能还需要在循环data之前使用可选的链接运算符(或if -check):

data?.forEach((d) => {
  /* ... */
});

In case the setData(data) function you call after doesn't accept undefined , you're probably better off with an explicit if -check and either calling setData(null) or not calling setData() at all.如果您调用的setData(data)函数不接受undefined ,则最好使用显式if -check 并调用setData(null)或根本不调用setData()

Discrepancies between JSON types and model types JSON 类型和模型类型之间的差异

There are discrepancies between the JSON data you retrieve, and the way you wish to model them in your application.您检索的 JSON 数据与您希望在应用程序中对其建模的方式之间存在差异。 First of all, it's more readable and convenient to type a single EventViewerDataType object (instead of EventViewerDataTypes ), and then use EventViewerDataType[] whenever you need an array.首先,键入单个EventViewerDataType对象(而不是EventViewerDataTypes )更具可读性和方便性,然后在需要数组时使用EventViewerDataType[]

Based on your processing logic, this is how I think EventViewerDataType should be typed:根据您的处理逻辑,我认为EventViewerDataType应该是这样输入的:

interface EventViewerDataType {
  date: Date | null;
  site: string;
  type: string;
  value: number;
}

Then, since your JSON seems to contain only strings, I would use a mapped type to define the data transfer object as:然后,由于您的 JSON 似乎只包含字符串,我将使用映射类型将数据传输对象定义为:

type StringValues<T> = {
  [K in keyof T]: string;
}

Then, in your processing logic, instead of using forEach() , use map() to map from your JSON format objects ( StringValues<EventViewerDataType>[] ) to your model objects ( EventViewerDataType[] ).然后,在您的处理逻辑中,使用map()从您的 JSON 格式对象( StringValues<EventViewerDataType>[] )映射到您的模型对象( EventViewerDataType[] ),而不是使用forEach() ) 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM