React Typescript 从 Spring Data REST API 获取“属性'_embedded'不存在”问题

Posted

技术标签:

【中文标题】React Typescript 从 Spring Data REST API 获取“属性\'_embedded\'不存在”问题【英文标题】:React Typescript fetch from Spring Data REST API "Property '_embedded' does not exist" issueReact Typescript 从 Spring Data REST API 获取“属性'_embedded'不存在”问题 【发布时间】:2021-09-22 19:54:23 【问题描述】:

我正在使用 Typescript 构建一个 React 应用程序,当我发送类似的请求时,它会从 Spring Data REST API(JPA 存储库)获取数据 “GET http://localhost:8080/notifications/1”,来自特定的 id,我的 JSON 响应没有打字稿问题,因为它看起来像这样:


  "title" : "titulo",
  "content" : "conteúdo",
  "notificationPriority" : "medium",
  "seen" : true,
  "notificationType" : "Student",
  "createdAt" : null,
  "_links" : 
    "self" : 
      "href" : "http://localhost:8080/notifications/1"
    ,
    "notification" : 
      "href" : "http://localhost:8080/notifications/1"
    ,
    "phase" : 
      "href" : "http://localhost:8080/notifications/1/phase"
    ,
    "modality" : 
      "href" : "http://localhost:8080/notifications/1/modality"
    
  

所以在一个 react 组件中,我可以只使用“data.title”访问,因为提取的 useEffect 完全没问题,但是当我执行“GET http://localhost:8080/notifications”之类的请求时,JSON响应如下:


  "_embedded" : 
    "notifications" : [ 
      "title" : "titulo",
      "content" : "conteúdo",
      "notificationPriority" : "medium",
      "seen" : true,
      "notificationType" : "Student",
      "createdAt" : null,
      "_links" : 
        "self" : 
          "href" : "http://localhost:8080/notifications/1"
        ,
        "notification" : 
          "href" : "http://localhost:8080/notifications/1"
        ,
        "phase" : 
          "href" : "http://localhost:8080/notifications/1/phase"
        ,
        "modality" : 
          "href" : "http://localhost:8080/notifications/1/modality"
        
      
    ]
  ,
  "_links" : 
    "self" : 
      "href" : "http://localhost:8080/notifications"
    ,
    "profile" : 
      "href" : "http://localhost:8080/profile/notifications"
    
  ,
  "page" : 
    "size" : 20,
    "totalElements" : 2,
    "totalPages" : 1,
    "number" : 0
  

它应该只访问“data._embedded.notifications.title”并且它应该在反应组件中呈现,但是打字稿在获取之前会签署一个错误,所以仍然是一个任何类型的空对象 ,只有一小部分组件正确呈现一秒钟,直到打字稿覆盖在错误屏幕中显示:

“类型‘’上不存在属性‘_embedded’。”

在组件中我将 data 设置为 any 以避免这种情况,我怎样才能让 typescript 理解在获取数据时会有 _embedded?

在组件中,我已经在等待加载渲染了。

import React from 'react';
import Footer from '../templates/Footer';
import TopBar from '../NavLogged';
import NotificationList from '../Lists/NotificationList';
import useGetApi from '../utils/hooks/useGetApi';

export default function NotificationsPage() 
  const [notificationData, isLoading] = useGetApi(
    initialUrl: "http://localhost:8080/notifications");
  return (
    <>
      <TopBar />
      isLoading ? null : 
        <NotificationList
            data=notificationData._embedded.notifications
            listTitle='Minhas Notificações'
          />
      
      <Footer />
    </>
  );


【问题讨论】:

【参考方案1】:

简而言之,您没有将notifications 输入为具有结构 的对象。要解决此问题,您需要使用type assertions。在这种情况下,您必须键入返回的数据结构:

type Notifications = 
  "_embedded": 
    notifications: Array<
      title: string;
      content: string;
      notificationPriority: string;
      seen: boolean;
      notificationType: string;
      createdAt: null;
      "_links": 
        self: 
           href: string;
        ;
        notification: 
           href: string;
        ;
        phase: 
           href: string;
        ;
        modality: 
           href: string;
        ;
      ;
    >;
  ;
  "_links": 
    self: 
      href: string;
    ;
    profile: 
      href: string;
    ;
  ;
  page: 
    size: number;
    totalElements: number;
    totalPages: number;
    number: number;
  ;
;

Typescript Playground


演示

演示代码

import * as React from "react";
import "./styles.css";

export type Todo = 
  userId: number;
  id: number;
  title: string;
  completed: boolean;
;

export default function App() 
  const [todo, setTodo] = React.useState( as Todo);
  const [error, setError] = React.useState("");

  React.useEffect(() => 
    const fetchTodo = async () => 
      try 
        const res = await fetch("https://jsonplaceholder.typicode.com/todos/1");
        const data = await res.json();

        setTodo(data);
       catch (error) 
        setError(error.toString());
      
    ;

    fetchTodo();
  );

  return (
    <div className="app">
      <h1>Todo</h1>
      error && <p className="error">error</p>
      Object.keys(todo).length > 0 ? (
        <div className="todo">
          <h1>Id: todo.id</h1>
          <h1>UserId: todo.userId</h1>
          <h1>Title: todo.title</h1>
          <h1>Completed: todo.completed.toString()</h1>
        </div>
      ) : (
        <p>Loading...</p>
      )
    </div>
  );

【讨论】:

非常感谢,特别是把通知类型放在这里。只需在通知列表中添加该道具,就可以像这样调用 data=notificationData as Notifications 并在列表组件中调用“data._embedded?.notifications 以确保在获取时通知列表仍然为空”

以上是关于React Typescript 从 Spring Data REST API 获取“属性'_embedded'不存在”问题的主要内容,如果未能解决你的问题,请参考以下文章

Typescript:如何从 react-bootstrap 导入特定组件

将 create-react-app 从 javascript 迁移到 typescript

React-native:从 javascript 迁移到 typescript

从 react-jsx 迁移到 typescript-tsx react

如何从react-navigation获取主题类型(Typescript)

从 React 组件中导出 TypeScript 类型的字符串属性值?