首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >类型Promise<any>上不存在TS属性。

类型Promise<any>上不存在TS属性。
EN

Stack Overflow用户
提问于 2021-04-02 12:53:56
回答 3查看 4.5K关注 0票数 0

当前正在尝试呈现从URL获取的数据。如果我在文件本身中console.log它可以正常工作。但是现在我想调用页面组件上的获取数据,这样我就可以将其呈现为TSX。

这是我获取数据的API文件,称为api.ts:

代码语言:javascript
运行
复制
export const getVideoInfo = async () => {
  try {
    const getVideos = await fetch(
      "url"
    );
    const videos = await getVideos.json();
    return videos;
  } catch (e) {
    console.log(e);
  }
};

然后还有另一个文件(在这里,我试图找到一个与url中的散列匹配的文件,名为useCourseDetail.ts):

代码语言:javascript
运行
复制
import { useLocation } from "react-router";
import { getVideoInfo } from "../../api/Api";
import { Slugify } from "../../components/Util/Slugify";

export const FindCourseDetail = async () => {
  const { hash } = useLocation();
  const slugifiedHash = Slugify(hash);
  const data = await getVideoInfo();


  if (hash) {
    const video = data.videos.find(
      (v) =>
        Slugify(v.title, {
          lowerCase: true,
          replaceDot: "-",
          replaceAmpersand: "and",
        }) === slugifiedHash
    );
    return video;

  } else {
    return data.videos[0];

  }
};

在这两个文件中我都得到了我想要的对象。现在,我想使用对象中的内容在页面文件中呈现一些tsx,名为: CourseDetail.tsx。

代码语言:javascript
运行
复制
import { FindCourseDetail } from "./FindCourseDetail";

type Video = {
  title: string;
  description?: string;
  thumbnail?: string;
  videoid?: string;
  chapter: boolean;
  duration: number;
  subtitles: [];
};

export const CourseDetail = () => {
  const videoObject = FindCourseDetail(); 


  return (
    <div>
      <h2>Content player</h2>
      <h2>{videoObject.title}</h2>
    </div>
  );
};

而'videoObject.title‘会给我一个错误:属性'title’在‘承诺’类型上不存在。

这是公平的,我认为,因为如果我console.log,这是一个承诺。但我不知道我怎么能写成这样的东西,让它发挥作用。所以应该是这样的:const videoObject = await FindCourseDetail();。但这是不可能的,因为组件不是异步的,直接从react路由器调用。

我试图将useCourseDetail的函数复制到CourseDetail中。如果我使用useState和useEffect,这是可行的。但这有点混乱,感觉不太好,因为默认状态是一个带有null的对象。见下面的代码:

代码语言:javascript
运行
复制
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import { getVideoInfo } from "../../api/Api";
import { Slugify } from "../../components/Util/Slugify";

type Video = {
  title: string;
  description?: string;
  thumbnail?: string;
  videoid?: string;
  chapter: boolean;
  duration: number;
  subtitles: [];
};

export const CourseDetail = () => {
  const { hash } = useLocation();

  const [videoData, setVideoData] = useState<Video>({
    title: null,
    description: null,
    thumbnail: null,
    videoid: null,
    chapter: null,
    duration: null,
    subtitles: null,
  });

  useEffect(() => {
   findCourseData();
  }, []);

   const findCourseData = async () => {
     const slugifiedHash = Slugify(hash);
     const data = await getVideoInfo();

     if (hash) {
       const video = data.videos.find(
         (v) =>
           Slugify(v.title, {
             lowerCase: true,
             replaceDot: "-",
             replaceAmpersand: "and",
           }) === slugifiedHash
       );
       setVideoData(video);
     }
   };

  return (
    <div>
      <h2>Content player</h2>
      <h2>{videoObject.title}</h2>
    </div>
  );
};

我有一种感觉,这不是一个大的问题要解决,但我不知道它是哪里出了问题,我怎么能解决这个问题。

编辑:我尝试了以下方法:

代码语言:javascript
运行
复制
const [newData, setNewData] = useState({});

  const getData = async () => {
    try {
      const apiValue = await FindCourseDetail();
      setNewData(apiValue);
    } catch (err) {
      // error handling
    }
  };
  getData();

return (
    <div>
      <h2>Content player</h2>
      {newData && <h2>{newData.title}</h2>}
    </div>
  );

或:FindCourseDetail().then(videoObject => setNewData(videoObject))

现在它将抛出相同的错误:类型'{}‘上不存在属性'title’。

如果我将空对象作为默认状态删除,它会说:它可能是未定义的。

如果在默认状态下写null,它当然可以工作。但我不认为这是正确的方法:

代码语言:javascript
运行
复制
const [newData, setNewData] = useState({
    title: null,
    description: null,
    thumbnail: null,
    videoid: null,
    chapter: null,
    duration: null,
    subtitles: null,
  });

编辑2:

代码语言:javascript
运行
复制
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import { getVideoInfo } from "../../api/Api";
import { Slugify } from "../../components/Util/Slugify";

type Video = {
  title: string;
  description?: string;
  thumbnail?: string;
  videoid?: string;
  chapter: boolean;
  duration: number;
  subtitles: [];
};

export const CourseDetail = () => {
  const { hash } = useLocation();
  
  const [videoData, setVideoData] = useState<Video>({
    title: null,
    description: null,
    thumbnail: null,
    videoid: null,
    chapter: null,
    duration: null,
    subtitles: null,
  });

  const findCourseData = async () => {
    const slugifiedHash = Slugify(hash);
    const data = await getVideoInfo();

    if (hash) {
      const video = data.videos.find(
        (v) =>
          Slugify(v.title, {
            lowerCase: true,
            replaceDot: "-",
            replaceAmpersand: "and",
          }) === slugifiedHash
      );
      setVideoData(video);
    }
  };
  useEffect(() => {
    findCourseData();
  }, []);

  return (
    <div>
      <h2>Content player</h2>
      {videoData&& <h2>{videoData.title}</h2>}
    </div>
  );
};

这目前是可行的,但正如您所看到的,我在组件中复制和粘贴了函数本身。因此,我尝试了以下代码:

代码语言:javascript
运行
复制
type Video = {
  title: string;
  description?: string;
  thumbnail?: string;
  videoid?: string;
  chapter: boolean;
  duration: number;
  subtitles: [];
};

export const CourseDetail = () => {

  const [newData, setNewData] = useState<Video>(null);

  
  const getData = async () => {
    try {
      const apiValue = await FindCourseDetail();
      console.log(apiValue);
      setNewData(apiValue);
    } catch (e) {
      console.log('catch')
      console.log(e)
    }
  };

   useEffect(() => {
    getData();
  }, []);

  return (
    <div>
      <h2>Content player</h2>
      {newData&& <h2>{newData.title}</h2>}
    </div>
  );

这将不会运行,捕获将被触发,这是错误日志:

代码语言:javascript
运行
复制
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
 1. You might have mismatching versions of React and the renderer (such as React DOM)
 2. You might be breaking the Rules of Hooks
 3. You might have more than one copy of React in the same app

不知道为什么。这是FindCourseDetail的代码,称为:

代码语言:javascript
运行
复制
import { useLocation } from "react-router";
import { getVideoInfo } from "../../api/Api";
import { Slugify } from "../../components/Util/Slugify";

export const FindCourseDetail = async () => {
  const { hash } = useLocation();
  const slugifiedHash = Slugify(hash);
  const data = await getVideoInfo();

  if (hash) {
    const video = data.videos.find(
      (v) =>
        Slugify(v.title, {
          lowerCase: true,
          replaceDot: "-",
          replaceAmpersand: "and",
        }) === slugifiedHash
    );
    return video;

  } else {
    return data.videos[0];

  }
};
EN

回答 3

Stack Overflow用户

发布于 2021-04-02 14:55:04

您可能应该继续使用useEffect方法,但应该将(泛型)类型的useState声明为一个联合类型,包括null或视频数据。然后使用类型保护来消除空值的情况(不要呈现它)。

像这样..。

代码语言:javascript
运行
复制
const [videoData, setVideoData] = useState<Video|null>(null);

..。

代码语言:javascript
运行
复制
  return (
    <div>
      <h2>Content player</h2>
      {videoData && <h2>{videoData.title}</h2>}
    </div>
  );
票数 0
EN

Stack Overflow用户

发布于 2021-04-02 19:51:08

修好了!我正在调用FindCourseDetail内部的FindCourseDetail钩子。我通过在当前文件中调用useLocation钩子来修复它,并将其作为FindCourseDetail的支柱。

票数 0
EN

Stack Overflow用户

发布于 2022-10-06 00:09:54

您的情况更加具体和复杂,但我遇到了同样的问题,通常我理解以下几个问题:这似乎是因为您试图访问返回的回调值上的属性。示例:

代码语言:javascript
运行
复制
const user = getUser(id); // <= async function
user.property // <= ts will complain as user is going to be a Promise<any>

解决方案

代码语言:javascript
运行
复制
const user = await getUser(id); // <= add await
user.property // <= now it will be avaiable
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66919650

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档