【问题标题】:How to use useEffect and for loop to generate multiple JSX elements如何使用 useEffect 和 for 循环生成多个 JSX 元素
【发布时间】:2021-03-18 15:12:34
【问题描述】:

我想使用 useEffect 和 for-loop 来生成多个 JSX 元素,但在这种情况下没有渲染任何内容。

警告代码:“React Hook useEffect 缺少依赖项:'renderInfoCard'。要么包含它,要么删除依赖数组 react-hooks/exhaustive-deps”

import React, { useState, useEffect } from 'react';
import InfoCard from '../components/InfoCard.jsx';
import { getScenicSpotRequest } from '../request test.js';

function MainScreen() {

  const [renderInfoCard, setRenderInfoCard] = useState(null);
  const [renderInfoCardArray, setRenderInfoCardArray] = useState([]);

  useEffect(() => {
    //data recieve from axios request
    getScenicSpotRequest().then(result => {
    //want to use useEffect and for loop to generate multiple JSX elements 
      for (let i = 0; i < result.length; i++) {
        setRenderInfoCard(<InfoCard Name={result[i].Name} Description={result[i].Description} Picture={result[i].Picture.PictureUrl1} />);
        setRenderInfoCardArray[i] += renderInfoCard;
      }
    });
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        <Navbar NavbarTitle="ScenicSpot" />
        {renderInfoCardArray}
      </header>
    </div>
  );
}

export default MainScreen;

【问题讨论】:

  • 您是否尝试过在警告中添加缺少的依赖项?

标签: javascript reactjs for-loop jsx use-effect


【解决方案1】:

我不会将组件置于状态(而且您也不应该改变状态)。相反,请等待所有结果返回,然后立即使用 all 结果设置状态。返回 JSX 时,然后您可以通过映射结果(如果存在)来创建组件。

function MainScreen() {
  const [sceneResults, setSceneResults] = useState([]);
  useEffect(() => {
    getScenicSpotRequest()
      .then(setSceneResults);
      // .catch(handleErrors); // don't forget this - don't want unhandled rejections
  }, [setSceneResults]); // this will not change, so it's safe to put in the dependency array
  return (
    <div className="App">
      <header className="App-header">
        <Navbar NavbarTitle="ScenicSpot" />
        {sceneResults.map(result => (
          <InfoCard Name={result.Name} Description={result.Description} Picture={result.Picture.PictureUrl1} />)
        )}
      </header>
    </div>
  );
}

我把setSceneResults放到了效果依赖数组中以满足linter,不过没关系,对state setter的引用是稳定的,所以它只会在mount时运行。

【讨论】:

  • lmaoo 我正要完成输入这个 xD
【解决方案2】:

不要使用状态来存储元素,使用状态来存储请求值然后map通过这些值来渲染

import React, { useState, useEffect } from 'react';
import InfoCard from '../components/InfoCard.jsx';
import { getScenicSpotRequest } from '../request test.js';

function MainScreen() {

  const [infoCards, setInfoCards] = useState();

  useEffect(() => {
    //data recieve from axios request
    getScenicSpotRequest().then(result => setInfoCards(result));
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        <Navbar NavbarTitle="ScenicSpot" />
        {infoCards.map(infoCard => (<InfoCard key={infoCard.Id} Name={infoCard.Name} Description={infoCard.Description} Picture={infoCard.Picture.PictureUrl1} />))}
      </header>
    </div>
  );
}

export default MainScreen;

【讨论】:

  • getScenicSpotRequest().then(setInfoCards); 写成getScenicSpotRequest().then(result =&gt; setInfoCards(result)); 时,您的答案有效,谢谢!
【解决方案3】:

使用@CertainPerformance 的答案,它会弹出一个警告,即“警告:遇到两个具有相同密钥的孩子”。

为了解决这个问题,我在 JSX 中添加了 key={infoCard.ID}

function MainScreen() {

  const [sceneResults, setSceneResults] = useState([]);
  useEffect(() => {
    getScenicSpotRequest().then(setSceneResults);
  }, [setSceneResults]); 

  return (
    <div className="App">
      <header className="App-header">
        <Navbar NavbarTitle="ScenicSpot" />
        {sceneResults.map((infoCard) => (<InfoCard key={infoCard.ID} Name={infoCard.Name} Description={infoCard.Description} Picture={infoCard.Picture.PictureUrl1} />))}
      </header>
    </div>
  );
}

export default MainScreen;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-10
    • 2021-04-26
    • 2021-04-11
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多