Context
I'm learning React so I'm building a basic app where users can add a name and phone number. The POST request to add a person to the phonebook app was working fine initially and when I checked my local server, I could see a new user was added. However, I now received the following error message and the app doesn't work:
react-dom.development.js:67 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
App.js code
import React, { useState, useEffect } from 'react'
import axios from 'axios'
import PersonForm from './components/personform'
import Persons from './components/persons'
import Filter from './components/filter'
const App = () => {
const [persons, setPersons] = useState([])
const [ newName, setNewName ] = useState('')
const [ newNumber, setNewNumber ] = useState('')
const [ searchTerm, setSearchTerm] = useState('')
const [ searchResults, setSearchResults ] = useState([])
const handleNewName = (event) => setNewName(event.target.value)
const handleNewNumber = (event) => setNewNumber(event.target.value)
const handleChange = (event) => setSearchTerm(event.target.value)
const addPerson = (event) => {
event.preventDefault()
console.log("button clicked", event.target)
const personsCopy = [...persons]
const personObj = {
name:newName,
number: newNumber,
}
axios
.post("http://localhost:3001/persons", personObj)
.then(response => {
setPersons(personsCopy, persons.concat(response.data))
setNewName('')
})
const namesArr = personsCopy.map(person => person.name)
const nameExists = namesArr.some(names => names === personObj.name)
if(nameExists){
alert(`${personObj.name} already exists`)
} else{
setPersons(personsCopy.concat(personObj))
}
}
useEffect(addPerson, [])
useEffect(() => {
const results = persons.filter(person =>
person.name.toLowerCase().includes(searchTerm)
)
setSearchResults(results)
}, [searchTerm])
const getData = () => {
console.log('effect')
axios
.get('http://localhost:3001/persons')
.then(response => {
setPersons(response.data)
})
}
useEffect(getData, [])
return (
<div>
<h2>Phonebook</h2>
<Filter value={searchTerm} onFilterChange={handleChange}/>
<PersonForm onFormSubmit={addPerson} name={newName} onNameChange={handleNewName} number={newNumber} onNumberChange={handleNewNumber}/>
<h2>Numbers</h2>
<Persons filteredArr={searchResults} data={persons}/>
</div>
)
}
export default App
I've added the dependency array to the useEffect where I'm calling the POST request (addPerson function), but the error still appears. What causes a component to unmount and what's the best way to resolve this?
Edit I've updated the addPerson function to the following:
const addPerson = (event) => {
let isMounted = true
event.preventDefault()
console.log("button clicked", event.target)
const personsCopy = [...persons]
const personObj = {
name:newName,
number: newNumber,
}
axios
.post("http://localhost:3001/persons", personObj)
.then(response => {
if (isMounted) {
setPersons(personsCopy, persons.concat(response.data))
setNewName('')
}
})
return () => { isMounted = false }
}
useEffect(addPerson, [])
However, I'm still seeing the same error message