skip to Main Content

Imagine the following situation: I have a registration flow in which some parts of this registration are saved in the session storage to be sent at the end of the flow for an API request. On one of these screens, I select some information and, to add the cards to this list of companies created, I open a modal component and save this information set in the modal in the session to retrieve it on the original screen and include it in the list. However, since this screen has already been loaded, the useeffect has no effect and if I pass the original list as a parameter, it enters an infinite loop.
How can I solve this?

Json example in principal screen:

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

UseEffect:

  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.

add button modal component:

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

session json example:

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

I need to include the json value that is taken from the session and set it in the cards field of the array within the list of objects that already exists on the main screen as soon as the modal closes, compared by the id as seen in the code, just once without entering a loop.

2

Answers


  1. Chosen as BEST ANSWER

    was resolved by modifying the working of useEffect to a function, keeping the same code and the component call looked like:

    <ModalCadastroEmpresas onClose={handleModalClose}>
    

    and component like:

    const ModalCadastroEmpresas = ({ onClose }) =>
    

    calling the function passed by context when clicking the button to close the modal.


  2. You should ensure that the useEffect runs only once after the modal closes and the session data is set. Instead of depending on dataSourceListTESTE, you can use an empty dependency array [] and include a check to prevent multiple runs.

    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
    

    The isCardAdded ref is used to track if the new card data has been processed and added to the list, this prevents the useEffect from running again and modifying the state, which would cause an infinite loop.

    The useEffect now runs only once, as indicated by the empty dependency array [], inside the useEffect, it checks if there is a new card in the session storage and if it hasn’t been added yet (checked via isCardAdded.current).

    If a new card is found in the session storage, it is parsed and added to the relevant company’s list of cards. The isCardAdded.current flag is then set to true to ensure the effect doesn’t run again.

    The session storage is cleared after the card is processed to avoid reprocessing the same data if the component re-renders for some reason.

    If this solution does not align with your expectations, let me know.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search