繁体   English   中英

以正确的顺序放置反应钩子

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM