使用 useEffect 将项目添加到对象数组中的列表属性

问题描述 投票:0回答:1

想象一下以下情况:我有一个注册流程,其中注册的某些部分保存在会话存储中,以便在 API 请求流程结束时发送。在其中一个屏幕上,我选择一些信息,为了将卡片添加到创建的公司列表中,我打开一个模式组件并将此信息集保存在会话中的模式中,以便在原始屏幕上检索它并将其包含在名单。但是,由于该屏幕已经加载,因此 useeffect 不起作用,如果我将原始列表作为参数传递,它将进入无限循环。 我该如何解决这个问题?

主屏幕中的 Json 示例:

novoJsonEmpresa = { ...jsonEmpresa, company: id, companyName: name, cards: [],  // useeffect include session json here id: idCompany, };

使用效果:

  const [dataSourceListTESTE, setDataSourceListTESTE] = useState([]);

  useEffect(() => {
    let cartaoNovo = sessionStorage.getItem("jsonCartao");
    
    if (cartaoNovo) {
      cartaoNovo = JSON.parse(cartaoNovo);
      setDataSourceListTESTE((prevList) => 
        prevList.map((empresa) => {
          if (empresa.id == cartaoNovo.id) {
            return {
              ...empresa,
              cartoes: [...empresa.cartoes, cartaoNovo],
            };
          }
          return empresa; 
        })
      );
    }

    console.log(dataSourceListTESTE);
  }, [dataSourceListTESTE]); // when I pass this argument the list goes into infinite loop, if I don't pass any argument then this usage effect won't have any effect.

添加按钮模态组件:

  const handleAdicionar = () => {
    sessionStorage.setItem('jsonCartao', JSON.stringify(jsonCartao));
    setIsModalOpen(false);
  };

会话 json 示例:

{ "id":"1", "CartaoId":"example", "TipoCartao":"example", "NumeroCartao":"example" }

我需要包含从会话中获取的 json 值,并将其设置在模式关闭后主屏幕上已存在的对象列表中数组的卡片字段中,并通过 id 进行比较,如代码,只需一次,无需进入循环。

javascript reactjs arrays react-hooks session-storage
1个回答
0
投票

您应该确保 useEffect 仅在模式关闭并设置会话数据后运行一次。您可以使用空依赖数组 [] 并包含检查以防止多次运行,而不是依赖于 dataSourceListTESTE。

const [dataSourceListTESTE, setDataSourceListTESTE] = useState([]);
  const isCardAdded = useRef(false); // Ref to track if card has been added

  useEffect(() => {
    let cartaoNovo = sessionStorage.getItem("jsonCartao");

    if (cartaoNovo && !isCardAdded.current) {
      cartaoNovo = JSON.parse(cartaoNovo);
      setDataSourceListTESTE((prevList) =>
        prevList.map((empresa) => {
          if (empresa.id === cartaoNovo.id) {
            return {
              ...empresa,
              cartoes: [...empresa.cartoes, cartaoNovo],
            };
          }
          return empresa;
        })
      );
      isCardAdded.current = true; // Set ref to true to prevent reprocessing
      sessionStorage.removeItem("jsonCartao"); // Optional: Clear session storage after processing
    }
  }, []); // Empty dependency array ensures this effect runs only once

isCardAdded ref 用于跟踪新卡数据是否已被处理并添加到列表中,这可以防止 useEffect 再次运行并修改状态,从而导致无限循环。

useEffect 现在只运行一次,如空依赖数组 [] 所示,在 useEffect 内部,它检查会话存储中是否有新卡以及是否尚未添加(通过 isCardAdded.current 检查) .

如果在会话存储中发现新卡,则会对其进行解析并将其添加到相关公司的卡列表中。然后将 isCardAdded.current 标志设置为 true 以确保效果不会再次运行。

处理卡片后会清除会话存储,以避免组件由于某种原因重新渲染时重新处理相同的数据。

如果此解决方案不符合您的期望,请告诉我。

© www.soinside.com 2019 - 2024. All rights reserved.