簡體   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