[英]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.