【问题标题】:State update doesn't re-render component in ReactJS状态更新不会在 ReactJS 中重新渲染组件
【发布时间】:2021-08-22 16:04:30
【问题描述】:

我有一个组件,其中有这个 useEffect:

  const [charactersInfo, setCharactersInfo] = useState(null);

  const [page, setPage] = useState(1);

  useEffect(() => {
    fetch(`https://api/api/character/?page=${page}`)
      .then((res) => res.json())
      .then((result) => {
        setCharactersInfo(result);
      });
  }, [page]);

每当我的page 状态更新时,都会有不同的数据来自 api 预期。但问题是每当新的setCharactersInfo(result) 发生时,它都不会显示新数据。

我将我的 setPage 状态函数作为道具传递给该组件:

   <PaginationButtons
          data={charactersInfo}
          updatePage={(number) => {
            setPage(number);
          }}
        />

这是一个可重用的组件,它生成按钮,除了这个特定的组件外,它在任何地方都能正常工作。请问有什么建议吗?

import React, { useState, useEffect } from "react";

import "./PaginationButtons.css";

function PaginationButtons({ data, updatePage }) {
  const [buttonsArr, setButtonsArr] = useState([]);

  useEffect(() => {
    const finalArray = [];
    const { info } = data;
    // Not the best solution for situations in which
    // info.pages is big number(e.x 1000000) but since we know that
    // it mostly will be 34 or less so we can just loop through it :)
    for (let i = 1; i < info.pages + 1; i++) {
      finalArray.push(
        <button
          className="page_button"
          onClick={() => updatePage(i)}
          key={Math.random()}
        >
          {i}
        </button>
      );
    }
    setButtonsArr(finalArray);
  }, []);
  return <div className="button_container">{buttonsArr.map((el) => el)}</div>;
}

export default PaginationButtons;

data prop 是一个包含各种东西的对象,上面是应该显示的页面数。在这种特定情况下,它是 34,所以我使用 state 和 useEffect 循环遍历这个数字并将按钮存储在 state 数组中,然后映射它

【问题讨论】:

  • 您能否更新您的问题以包含所有相关代码?可以分享PaginationButtons组件代码吗?
  • @DrewReese 等一下
  • @DrewReese 我用 PaginationButtons 代码更新了问题
  • 我认为你在 PaginationButtons 的 useEffect 中缺少数据依赖

标签: reactjs


【解决方案1】:

您也应该处理子组件中的data 更改。 将data 传递给useEffect 依赖列表。

 useEffect(() => {
    const finalArray = [];
    const { info } = data;
    // Not the best solution for situations in which
    // info.pages is big number(e.x 1000000) but since we know that
    // it mostly will be 34 or less so we can just loop through it :)
    for (let i = 1; i < info.pages + 1; i++) {
      finalArray.push(
        <button
          className="page_button"
          onClick={() => updatePage(i)}
          key={Math.random()}
        >
          {i}
        </button>
      );
    }
    setButtonsArr(finalArray);
  }, [data]);

这应该对您有所帮助,无需维护状态。我看到 pages 不是数组,它只是键值对。

function PaginationButtons({ data, updatePage }) {
 const { info : { pages } } = data;
  return (
    <div className="button_container">
       <button
          className="page_button"
          onClick={() => updatePage(pages || 0)}
          key={pages}
        >
          {pages || 0}
        </button>
    </div>
  );
}

【讨论】:

  • 遗憾的是它没有修复它:(
  • 请检查新答案
【解决方案2】:

PaginationButtons 中的 useEffect 使用的是空依赖项,因此在 data 属性更新时它不会更新。据我所知,您无论如何都不需要buttonsArr 状态。从 props 存储派生状态也是反模式。只需将 data 数组属性映射到按钮即可。

使用随机值可能是指定 React 键的最不理想的方法。您可以使用映射数组索引,但您应该为每个页面元素使用唯一属性,或者如果没有,您应该使用生成的 GUID 来扩充数据。

function PaginationButtons({ data, updatePage }) {
  return (
    <div className="button_container">
      {data.?info?.pages?.map((page, i) => (
        <button
          className="page_button"
          onClick={() => updatePage(i)}
          key={i} // <-- or page.id if available
        >
          {i}
        </button>
      ))}
    </div>
  );
}

【讨论】:

  • data prop 是一个包含各种东西的对象,上面是应该显示的页面数。在这种特定情况下,它是 34,所以我使用 state 和 useEffect 循环遍历这个数字并将按钮存储在 state 数组中,然后映射它
【解决方案3】:

如其他答案所述,您需要添加 data 作为依赖项。此外,您不需要在buttonsArr 上调用map,因为您没有对其元素做任何事情。只需使用buttonsArr 本身

【讨论】:

    猜你喜欢
    • 2019-06-17
    • 2022-11-06
    • 2021-05-19
    • 2022-01-26
    • 2020-08-18
    • 2018-09-01
    • 1970-01-01
    • 2019-06-29
    • 2018-06-05
    相关资源
    最近更新 更多