skip to Main Content

Maybe it’s silly to ask this, but I’m stuck and I can’t go on.

Since i have added removePerson and the button funcionality, I always get a error in the Persons component

const Persons = ({persons, searchName, removePerson}) => {
  //console.log(searchName)
  const exp = new RegExp( searchName, 'i' );
  const result =  persons.filter(person => person.name.match(exp))
  console.log(result + "inside Persons")
  return (
    result.map(person => <p key = {person.name}>{person.name}: {person.number} 
      <button onClick={() => removePerson(person.id)}>Delete</button></p>)
  )
}

When I delete a user from db.json I get the following error:

persons.filter is not a function
TypeError: persons.filter is not a function 

If I remove the <button onClick={() => removePerson(person.id)}>Delete</button> functionality from Persons, the app works as expected.

const removePerson = (id) => {
    axios.get(`http://localhost:3001/persons/${id}`).then((response) => {
      const query = window.confirm(`Delete ${response.data.name} ?`);
      console.log(response.data.name);
      if (query) {
        axios
          .delete(`http://localhost:3001/persons/${id}`)
          .then((response) => console.log(response.data));
      }
      setTimeout(() => {
        personService.getAll().then((response) => setPersons(response));
      }, 1000);
    });
  }; 

Before adding removePerson it displayed the names perfectly.

const App = () => {

 const [ persons, setPersons] = useState([])
 const [ searchName, setSearchName] = useState('')
 ...
 return (
  ...
  <Persons persons={persons} searchName={searchName} removePerson= 
   {removePerson}/>
  ...
}
//services/persons.js
import axios from 'axios'
const baseUrl = 'http://localhost:3001/persons'

const getAll = () => {
  return axios.get(baseUrl)
}
...

Now I manage to delete the desired name from bd.json, but the app explodes.

//db.json
{
  "persons": [
    {
      "name": "Isaac Asimov",
      "number": "933445566",
      "id": 5
    },
    {
      "name": "Frederick Forsyth",
      "number": "400556688",
      "id": 6
    },
    {
      "name": "Fiodor Dostoyievski",
      "number": "999125645",
      "id": 7
    },
    ...

I’m fairly new to React and I think the problem is in the design of this component (Persons), and that I can’t combine these two functionalities in it, search and delete elements, but I don’t know how to solve it without turning almost everything around.

Any help would be appreciated.

2

Answers


  1. It seems like you are setting the persons state as the object from the response, instead of the array inside of it:

    // in service/persons.js
    const getAll = () => {
      return axios.get(baseUrl)
    }
    
    // inside the removePerson function
    setTimeout(() => {      
      personService.getAll().then((response) => 
      setPersons(response));
    }, 1000);
    

    which means the persons state would currently contain the following object: { persons: [/*...*/] } which means there isn’t a .filter function inside of it, that’s why you’re receiving such error.

    I guess you wanted to access the persons array inside of it, such as:

    setTimeout(() => {      
      personService.getAll().then((response) => 
      setPersons(response.persons));
    }, 1000);
    
    Login or Signup to reply.
  2. persons.filter is not a function

    If persons.filter is not a function then persons is not an array. So what is it? If this operation:

    personService.getAll()
    

    results in the JSON you’re showing near the end of the question then that is indeed not an array. It’s an object. You can set the state to the property on that object which has an array. For example:

    .then((response) => setPersons(response.persons))
    

    Basically, it’s important to observe and understand your own data structures. Objects and arrays are different things. (Technically an array is an object, but it’s one which has a specific structure.)


    As an aside… This looks like a hack:

    if (query) {
      axios
        .delete(`http://localhost:3001/persons/${id}`)
        .then((response) => console.log(response.data));
    }
    setTimeout(() => {
      personService.getAll().then((response) => setPersons(response.persons));
    }, 1000);
    

    What exactly is the purpose of setTimeout here? Why always wait exactly one second? If the goal is to fetch the updated data after the delete operation, then do it after the delete operation:

    if (query) {
      axios
        .delete(`http://localhost:3001/persons/${id}`)
        .then((response) => personService.getAll())
        .then((response) => setPersons(response.persons));
    }
    

    Or, if you still want to log the delete response to the console:

    if (query) {
      axios
        .delete(`http://localhost:3001/persons/${id}`)
        .then((response) => {
          console.log(response.data);
          return personService.getAll();
        )
        .then((response) => setPersons(response.persons));
    }
    

    Don’t use artificial timers as a workaround to asynchronous code.

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