Coffee
Coffee

Reputation: 11

React useState updates array but not the info on screen

i am trying to make a recipe app.

I have a form where i can enter an ingredient and then with the 'plus' sign add a new textfield. It seems that the ingredienst are getting inserted in my array using useState.

The problem occurs when i want to delete an item. The item seems to get deleted from the array so thats good, but the textfield aren't updating accordingly

Adding ingredients:

Form

console.log

Removing ingredients (i removed 'bbb'):

after removing bbb

console.log

So the array seems to update fine, but the form is not. On the form the last entry gets deleted.

my code:

import React, { useState } from 'react'
import TextField from '@mui/material/TextField';
import { IconButton, InputAdornment } from '@material-ui/core';
import { MdAddBox, MdIndeterminateCheckBox } from 'react-icons/md';

function Formulier () {

  const [ingredient, setIngredient] = useState([{ ingredient: "" }]);
  console.log(ingredient);

  const handleAddIngredient = () => {
    setIngredient([...ingredient, { ingredient: "" }]);
    // console.log(test);
  };

  const handleRemoveIngredient = (index) => {
    const list = [...ingredient];
    // list.splice(index, 1);
    setIngredient(list.filter((_, i) => i !== index));
    console.log([list]);
  };

  const handleChangeIngredient = (e, index) => {
    const { value } = e.target;
    const newIngredient = [...ingredient];
    newIngredient[index] = value;
    setIngredient(newIngredient);
  };

    return (
        <form>
          <div>
              {ingredient.map((singleIngredient, index) => (

                <div key={index}>
                    <div>
                      <TextField
                        value={singleIngredient.value}
                        onChange={(e) => {handleChangeIngredient(e, index)}}
                        label="Ingredienten"
                        InputProps={{
                          endAdornment: 
                            <InputAdornment position="end">
                              {ingredient.length !== 1 && (
                                <IconButton onClick={() => handleRemoveIngredient(index)}>
                                  <MdIndeterminateCheckBox color='red' size={30}/>
                                </IconButton>
                              )}
                            </InputAdornment>}}
                      />
                    </div>

                    <div>
                      {ingredient.length -1 === index && (
                        <IconButton onClick={handleAddIngredient}>
                          <MdAddBox color='green' size={30}/>
                        </IconButton>
                      )}
                    </div> 
                </div>
              ))}      
          </div>
        </form>  
    )
  }
  
  export default Formulier;

Upvotes: 1

Views: 45

Answers (3)

Coffee
Coffee

Reputation: 11

I rewrote my component from scratch with your tips and now it’s working fine. Can’t really find what I did erin in the first one still.

Upvotes: 0

G&#248;ran Cantona
G&#248;ran Cantona

Reputation: 641

The reason is very likely that you're using index as a key in your map function. React uses the key to identify an item inside the array, and when you delete something, another item probably takes the place of the deleted one. Try using the text itself as key, and see if that helps.

Upvotes: 0

Irfanullah Jan
Irfanullah Jan

Reputation: 3892

This is probably because you have used key={index}. Try another unique key e.g. ingredient id.

From React docs:

We don’t recommend using indexes for keys if the order of items may change. This can negatively impact performance and may cause issues with component state. Check out Robin Pokorny’s article for an in-depth explanation on the negative impacts of using an index as a key. If you choose not to assign an explicit key to list items then React will default to using indexes as keys.

Source: https://reactjs.org/docs/lists-and-keys.html#keys

Upvotes: 1

Related Questions