Home > OS >  React useState updates array but not the info on screen
React useState updates array but not the info on screen

Time:04-15

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;

CodePudding user response:

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

CodePudding user response:

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.

  • Related