0

Please help me. I am new in React and try to build an application to add contact in Local storage and delete contact. Following are the code of my App.js

import React, {useState, useEffect} from 'react'
import {uuid} from 'uuidv4'
import AddContact from './AddContact'
import ContactList from './ContactList'
import Header from './Header'

function App() {
  //useState Hooks in React
  const LOCAL_STORAGE_KEY = 'contacts'
  const [contacts, setContacts] = useState([])

  const addContactHandler = (contact) => {
    console.log(contacts)
    setContacts([...contacts, {id: uuid(), ...contact}])
  }

  const removeContactHandler = (id) => {
    const newContactList = contacts.filter((contact) => {
      return contact.id !== id
    })
    setContacts(newContactList)
  }
  useEffect(() => {
    const retrieve_contact = JSON.parse(localStorage.getItem(LOCAL_STORAGE_KEY))
    if (retrieve_contact) {
      setContacts(retrieve_contact)
    }
  }, [])

  useEffect(() => {
    localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(contacts))
  }, [contacts])

  return (
    <div className="ui container">
      <Header />
      <AddContact addContactHandler={addContactHandler} />
      <ContactList contacts={contacts} getContactId={removeContactHandler} />
    </div>
  )
}

export default App

I got the error Uncaught RangeError: Maximum call stack size exceeded.

Please help me how can i remove this error. Thank you!

5
  • Please log retrieve_contact. I;d willing to bet that retrieve_contact is always true value Commented Feb 11, 2022 at 11:25
  • 1
    @captain-yossarian even if that is true, there is no reason why it should result in an infinite loop. That useEffect hook is only going to execute once. Commented Feb 11, 2022 at 11:55
  • @BenWainwright you are right Commented Feb 11, 2022 at 12:05
  • The problem i am facing in this line ` setContacts([...contacts, { id: uuid(), ...contact }]);` id:uuid() when i remove id: uuid() then i got the same key for each element Commented Feb 11, 2022 at 12:35
  • when exactly does it say it? after you click something or right away? it looks like more code and explanation will help to understand the problem more easily Commented Feb 12, 2022 at 19:11

1 Answer 1

1

You are updating react state inside useEffect, which triggers an infinite loop.

useEffect(() => {
    localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(contacts))
  }, [contacts])

In short, you told useEffect to run when there are changes to contacts (by passing them into the dependency array as the second param to useEffect), causing it to run every time contacts changes, which triggers a state change to contacts, which triggers the useEffect loop again, infinitely. If the array was empty, it would run once on start.

For what you are trying to do here, it makes more sense to update your store when you add or remove contacts, i.e. call the storage functions from within your event handlers.

Here's a working code sandbox with the code you provided.

Sign up to request clarification or add additional context in comments.

2 Comments

I dont quite follow your solution. Everytime contacts changes, the useEffect will fire. Shouldn't that only result in storing an item in local Storage? Why would the call to localStorage trigger a state change for contacts?
@MarkM I think you're right! I tried to get the sandbox to reproduce the error again, and was not able to sort it out. However, that maximum call exceeded is usually a result of updating state from inside useEffect. It could be happening elsewhere in the stack

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.