3vti1qhhvcgxwespkody · js ...· 3 小时前 · |
英勇无比的铁链 · JavaScript同步、异步、回调 - ...· 3 小时前 · |
腼腆的眼镜 · 泳池冲突引发的悲剧:真实版《搜索》发生之后 ...· 4 月前 · |
呐喊的皮蛋 · 丛林果汁漫画 - 抖音· 1 年前 · |
高大的滑板 · ubuntu(17):ubuntu下wps缺 ...· 1 年前 · |
沉着的大白菜 · 买纯电车,为啥首选纯电专属平台 ?AION ...· 1 年前 · |
勤奋的创口贴 · 搞笑漫画:灰姑娘的到付水晶鞋· 1 年前 · |
当前正在尝试呈现从URL获取的数据。如果我在文件本身中console.log它可以正常工作。但是现在我想调用页面组件上的获取数据,这样我就可以将其呈现为TSX。
这是我获取数据的API文件,称为api.ts:
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):
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。
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 (
<h2>Content player</h2>
<h2>{videoObject.title}</h2>
};
而'videoObject.title‘会给我一个错误:属性'title’在‘承诺’类型上不存在。
这是公平的,我认为,因为如果我console.log,这是一个承诺。但我不知道我怎么能写成这样的东西,让它发挥作用。所以应该是这样的:
const videoObject = await FindCourseDetail();
。但这是不可能的,因为组件不是异步的,直接从react路由器调用。
我试图将useCourseDetail的函数复制到CourseDetail中。如果我使用useState和useEffect,这是可行的。但这有点混乱,感觉不太好,因为默认状态是一个带有null的对象。见下面的代码:
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 (
<h2>Content player</h2>
<h2>{videoObject.title}</h2>
};
我有一种感觉,这不是一个大的问题要解决,但我不知道它是哪里出了问题,我怎么能解决这个问题。
编辑:我尝试了以下方法:
const [newData, setNewData] = useState({});
const getData = async () => {
try {
const apiValue = await FindCourseDetail();
setNewData(apiValue);
} catch (err) {
// error handling
getData();
return (
<h2>Content player</h2>
{newData && <h2>{newData.title}</h2>}
);
或:
FindCourseDetail().then(videoObject => setNewData(videoObject))
现在它将抛出相同的错误:类型'{}‘上不存在属性'title’。
如果我将空对象作为默认状态删除,它会说:它可能是未定义的。
如果在默认状态下写null,它当然可以工作。但我不认为这是正确的方法:
const [newData, setNewData] = useState({
title: null,
description: null,
thumbnail: null,
videoid: null,
chapter: null,
duration: null,
subtitles: null,
});
编辑2:
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 (
<h2>Content player</h2>
{videoData&& <h2>{videoData.title}</h2>}
};
这目前是可行的,但正如您所看到的,我在组件中复制和粘贴了函数本身。因此,我尝试了以下代码:
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 (
<h2>Content player</h2>
{newData&& <h2>{newData.title}</h2>}
);
这将不会运行,捕获将被触发,这是错误日志:
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的代码,称为:
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];
};
发布于 2021-04-02 14:55:04
您可能应该继续使用useEffect方法,但应该将(泛型)类型的useState声明为一个联合类型,包括null或视频数据。然后使用类型保护来消除空值的情况(不要呈现它)。
像这样..。
const [videoData, setVideoData] = useState<Video|null>(null);
..。
return (