我建立了一个简单的项目来提高我在react
框架中的技能,我的项目,它从API
中获取一些数据,称为Bored API,它提供了一些不同类别的活动,如烹饪或DIY等,并使用翻译器API
将活动翻译为阿拉伯语。我的问题是我做了两个hooks
,第一个是useBored
,它获取该活动并将其发送到称为useTranslate
的第二个hook
,该useTranslate
将文本发送到翻译器API
以便更好地理解,以下是代码:App.tsx
:
import React, { useEffect, useState } from "react";
import CardComp from "./components/CardComp";
import images no need to copy it here
const App: React.FC = () => {
const [final, setfinalD] = useState<string>(""); //this state used after I get the final text from translator
useEffect(() => {
console.log(final);
}, [final]);
return (
<div className=" bg-gradient-to-bl from-gray-700 via-gray-900 to-black flex justify-center items-center h-[100vh] w-[100vw]">
<div className="grid gap-2 grid-cols-2 grid-rows-3 ">
<CardComp
placeholder="تــعـلـوم"
image={education}
setD={setfinalD}
type={"education"}
/>
<CardComp
placeholder="نـشـاطـات"
image={kite}
setD={setfinalD}
type={"recreational"}
/>
<CardComp
placeholder="أجتـماعـيات"
image={social}
setD={setfinalD}
type={"social"}
/>
<CardComp
placeholder="أفعلها بـنـفسك"
image={diy}
setD={setfinalD}
type={"diy"}
/>
<CardComp
placeholder="عمل خــيـر"
image={social}
setD={setfinalD}
type={"charity"}
/>
<CardComp
placeholder="طـبخ"
image={cooking}
setD={setfinalD}
type={"cooking"}
/>
<CardComp
placeholder="أسـترخاء"
image={education}
setD={setfinalD}
type={"relaxation"}
/>
<CardComp
placeholder="عــمــل"
image={work}
setD={setfinalD}
type={"busywork"}
/>
</div>
{final ? <p>{final}</p> : null} // here print the translated text
</div>
);
};
export default App;
现在CardComp.tsx
:
import React from "react";
import { useBored } from "../hooks/useBored";
import { useTranslate } from "../hooks/useTranslate";
interface ICard {
placeholder: string;
image: string;
type: string;
setD: React.Dispatch<React.SetStateAction<string>>;
}
const CardComp: React.FC<ICard> = ({ placeholder, image, type, setD }) => {
const getTheData = () => { // *ERROR* came from here
const { data: dd } = useBored(type);
const { data, isLoading, error } = useTranslate(dd[0]);
if (isLoading === false) {
setD(data);
}
};
return (
<div>
<div
onClick={getTheData}
className="flex flex-col justify-center items-center p-7 cursor-pointer font-mono bg-[radial-gradient(ellipse_at_top_right,_var(--tw-gradient-stops))] from-blue-700 via-blue-800 to-gray-900"
>
<div className=" ">
<img src={image} className="w-[2.3em]" />
</div>
<h3>{placeholder}</h3>
</div>
</div>
);
};
export default CardComp;
现在useBored.ts
:
import { useState, useEffect } from "react";
export const useBored = (type: string) => {
const [data, setData] = useState<string[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [error, setError] = useState<string>("");
useEffect(() => {
fetch(`http://www.boredapi.com/api/activity?type=${type}`)
.then((r) => r.json())
.then((r) => (setIsLoading(false), setData([r.activity, r.link])))
.catch((e) => setError(e));
}, [type]);
console.log(data);
return { data };
};
最后一个钩子是useTranslate.ts
:
import { useState, useEffect } from "react";
export const useTranslate = (text: string) => {
const [data, setData] = useState<null | string>(null);
const [isLoading, setIsLoading] = useState<boolean>(true);
const [error, setError] = useState<string>("");
useEffect(() => {
fetch(`https://api.mymemory.translated.net/get?q=${text}&langpair=en|ar`)
.then((r) => r.json())
.then((r) => (setIsLoading(false), setData(r.matches[0].translation)))
.catch((e) => setError(e));
}, [text]);
return { data, isLoading, error };
};
如您所见,这是我的项目,错误来自CardComp
中的getTheData
函数,如果在函数之外使用hooks
,它会工作,但不是我想要的,* 错误 * 是:
请告诉我出了什么事,谢谢。
我用顺风做造型。
2条答案
按热度按时间nnsrf1az1#
不能从未将自身标识为react组件的函数调用任何钩子。由于您是新手,因此为了给予您一些知识,函数被标识为react函数组件,如下所示:
null
随后,您还应该从react类组件的render函数或从另一个函数组件返回组件,而不是像常规函数那样调用它(例如:组件()将引发错误.是使用react组件得正确方法).
现在,我们已经清楚了react组件是什么样子的,从这里你应该很清楚你的问题是什么。
你正在示例化你的钩子
useBored
你不能在
getTheData
函数中示例化你的钩子,因为它没有把自己标识为一个react组件(参考上面的要点)。因此,要解决这个问题,必须在
getTheData
函数之外示例化钩子。我想你可以修改你的代码库来遵循这一点。希望它有帮助。
wydwbb8l2#
在出现错误的CardComp组件getTheData函数中,文档显示不允许这样做(在一个函数中调用一个hook,该函数是一个onclick处理程序)。因此,您不能这样做。控制台错误中的链接显示,只能调用hook:
1.在函数组件主体的顶层
1.在自定义挂钩的顶级正文中
文档中还提到,您可以安装eslint-plugin-react-hooks插件来捕获这些错误
但这是有意义的--这些自定义钩子也调用useState和useEffect。它们是为了与组件的生命周期一起工作。在onClick处理程序中调用这些钩子是没有意义的,因为这超出了组件的生命周期,并由用户交互启动。useEffect在每次更新时运行,并可以选择在组件卸载时返回一个cleanup回调。在您的情况下,在单击按钮之前,不会在自定义钩子内调用useEffect,这会破坏预期的范例。
从你的两个钩子看,我觉得你是在一个onClick处理程序中获取数据。useEffect通常用于加载组件的初始数据,但不是在处理程序中。
我们将Redux与React结合使用,这样我们就可以调度一个动作来调用fetch,并让该动作调度一个带有fetch响应有效载荷的“response”动作,然后Reducer可以更新状态,CardComp将适当地重新渲染。