[英]Placing react hooks in proper order
我正在使用一個顯示博客列表的組件。 然后對於每個博客,我 map 在數組中的每個類別上顯示並顯示。 到目前為止的代碼是:
import React, { useState, useEffect } from "react";
import { connect } from "frontity";
import { GridWrap, GridRow, GridColumn } from "emotion-flex-grid";
import Link from "@frontity/components/link";
import CardContainer from "./index.style";
const Card = ({ state, post, libraries, categoryName }) => {
console.log("post", post);
const [categoryNameFromId, setCategoryNameFromId] = useState();
useEffect(() => {
fetch(`${state.source.api}wp/v2/categories/${cat}`)
.then((response) => response.json())
.then((data) => {
setCategoryNameFromId(data);
});
}, []);
return (
<GridColumn width={[12, 12, 6, 4, 4]} p={["none", "none", "s", "m"]} py={["s", "s", "s", "m"]} style={{display: `flex`, alignSelf: `stretch`}}>
<CardContainer>
<div className="info">
{post.acf.featured_media ? <img src={post.acf.featured_media.url} /> : <img src="https://images.unsplash.com/photo-1510337550647-e84f83e341ca?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=3289&q=80" />}
<Link link={`blog/${post.slug}`} className="title">
{post.title.rendered}
</Link>
<GridRow className="date-time">
<p className="date">{post.formatted_date}</p>
<p className="reading-time">reading time</p>
</GridRow>
<div className="excerpt"><libraries.html2react.Component html={post.excerpt.rendered} /></div>
</div>
<div className="share">
<GridRow justify="between">
<p>
{post.categories.map((cat) => {
return (
<>
<span>{categoryNameFromId && categoryNameFromId.name}, </span>
</>
)
})}
</p>
<div className="social-icons">
<i className="icon kap-facebook" />
<i className="icon kap-twitter" />
<i className="icon kap-linkedin" />
<i className="icon kap-mail" />
</div>
</GridRow>
</div>
</CardContainer>
</GridColumn>
)
}
export default connect(Card);
我遇到的問題是,我在控制台中收到一個錯誤,提示“未捕獲的 ReferenceError:cat 未定義”。 所以我試着把鈎子移到另一個地方,像這樣:
import React, { useState, useEffect } from "react";
import { connect } from "frontity";
import { GridWrap, GridRow, GridColumn } from "emotion-flex-grid";
import Link from "@frontity/components/link";
import CardContainer from "./index.style";
const Card = ({ state, post, libraries, categoryName }) => {
console.log("post", post);
return (
<GridColumn width={[12, 12, 6, 4, 4]} p={["none", "none", "s", "m"]} py={["s", "s", "s", "m"]} style={{display: `flex`, alignSelf: `stretch`}}>
<CardContainer>
<div className="info">
{post.acf.featured_media ? <img src={post.acf.featured_media.url} /> : <img src="https://images.unsplash.com/photo-1510337550647-e84f83e341ca?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=3289&q=80" />}
<Link link={`blog/${post.slug}`} className="title">
{post.title.rendered}
</Link>
<GridRow className="date-time">
<p className="date">{post.formatted_date}</p>
<p className="reading-time">reading time</p>
</GridRow>
<div className="excerpt"><libraries.html2react.Component html={post.excerpt.rendered} /></div>
</div>
<div className="share">
<GridRow justify="between">
<p>
{post.categories.map((cat) => {
const [categoryNameFromId, setCategoryNameFromId] = useState();
useEffect(() => {
fetch(`${state.source.api}wp/v2/categories/${cat}`)
.then((response) => response.json())
.then((data) => {
setCategoryNameFromId(data);
});
}, []);
return (
<>
<span>{categoryNameFromId && categoryNameFromId.name}, </span>
</>
)
})}
</p>
<div className="social-icons">
<i className="icon kap-facebook" />
<i className="icon kap-twitter" />
<i className="icon kap-linkedin" />
<i className="icon kap-mail" />
</div>
</GridRow>
</div>
</CardContainer>
</GridColumn>
)
}
export default connect(Card);
並且錯誤確實 go 消失了。 但我很確定這不是正確的方法。 有沒有辦法讓鈎子位於組件的頂部? 任何輸入都會很棒!
當組件已安裝時,對 API 的調用用於在useEffect
中,在這種情況下,您可以將useEffect
移到 JSX 之外並從那里調用 API。
useEffect(() => {
const promises = post.categories.map(cat => {
fetch(`${state.source.api}wp/v2/categories/${cat}`)
.then((response) => response.json());
});
Promise.all(promises).then(data => data.map(item => setCategoryNameFromId(item);))
}, []);
您需要存儲所有 api 調用的結果。 對於每個 post.categories 項獲取數據並保存,一旦完成,更新類別 state:
const [categories, setCategories] = useState([]);
useEffect(() => {
const fetchData = async (cat) => {
const categoryIdData = await fetch(`${state.source.api}wp/v2/categories/${cat}`).then(res => res.json())
return categoryIdData;
}
const updateData = async () => {
let categories = [];
post.categories.map(async (cat) => {
const catData = await fetchData(cat);
categories.push(catData);
});
setCategories(categories);
}
updateData();
}, []);
然后在模板中:
<p>
{categories.map((cat) => (<>
<span>{cat.name}, </span>
</>)
}
</p>
當然,您可以使用Promise.all來簡化它:
const [categories, setCategories] = useState([]);
useEffect(() => {
const updateData = async () => {
const categoriesFetch = post.categories.map(cat => fetch(`${state.source.api}wp/v2/categories/${cat}`).then(res => res.json()));
const categories = await Promise.all(categoriesFetch);
setCategories(categories);
}
updateData();
}, []);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.