Удалить один элемент в массиве ReactJS (React Hooks и Redux)

Я создаю приложение-рецепт с использованием стека MERN.

Проблема, на которой я застрял, - это попытка удалить ингредиент, найденный в массиве, внутри объекта рецепта. Мой объект рецепта выглядит так:

Объект рецепта MongoDB

Рядом с каждым ингредиентом есть крестик, который позволяет щелкнуть по нему, чтобы удалить.

<div>
      <ol className='pad5px20px'>
        {addIngredients.ingredients.map(data => (
          <div className='ingredient-item padTB5px' key={data}>
            <li>{data}</li>
            <span onClick={() => removeIngredient(data)}>
              <i className='fas fa-trash'></i>
            </span>{' '}
                  
          </div>
        ))}
      </ol>
    </div>

Функции addIngredients и removeIngredient выглядят следующим образом:

  const addIngredient = e => {
e.preventDefault();

if (query === '') return;

addIngredients.ingredients.push(query);
setIngredients(addIngredients);

setRecipe(prevState => ({
  ...prevState,
  ingredients: [
    ...prevState.ingredients,
    { id: Date.now(), ingredient: query }
  ]
}));
};

  const removeIngredient = data => {
const results = addIngredients.ingredients.filter(
  e => e.ingredients !== data
);
setIngredients(
  addIngredients.ingredients.filter(e => e.ingredients !== data)
);
};

Каждый раз, когда я удаляю ингредиент из своего списка, я получаю сообщение об ошибке "TypeError: Cannot read property 'map' of undefined".

Что-то мне здесь не хватает? Я работаю над этим приложением последние пару месяцев и застрял на этом конкретном моменте. Я подумал, что лучше будет использовать Redux, так как я смог удалить целый рецепт с помощью редуктора:

    case DELETE_RECIPE:
  return {
    ...state,
    recipes: state.recipes.filter(recipe => recipe._id !== action.payload),
    loading: false
  };

но как я могу выбрать один конкретный ингредиент?

Любые предложения будут ценны.

1 ответ

Я добавил примечания к вашим проблемам с кодом)

  const addIngredient = e => {
      e.preventDefault();

      if (query === '') return;

     ***STATE MUTATION***
      addIngredients.ingredients.push(query);
     setIngredients(addIngredients);

    setRecipe(prevState => ({
       ...prevState,
       ingredients: [
       ...prevState.ingredients,
       { id: Date.now(), ingredient: query }
  ]
}));
};

  const removeIngredient = data => {
    const results = addIngredients.ingredients.filter(
       e => e.ingredients !== data
    );
    ***You're adding ingredients object instead of addIngredients as you used in addIngredient method***
   setIngredients(
     addIngredients.ingredients.filter(e => e.ingredients !== data)
   );
};

addIngredients.ingredients.filter(e => e.ingredients !== data) возвращает отфильтрованные ингредиенты вместо добавок Ингредиенты с полем отфильтрованных ингредиентов

Как это должно быть

  const addIngredient = e => {
      e.preventDefault();

      if (query === '') return;

     setIngredients({
       ...addIngredients,
       ingredients: [
          ...addIngredients,
          query
       ]
     });

    setRecipe(prevState => ({
       ...prevState,
       ingredients: [
       ...prevState.ingredients,
       { id: Date.now(), ingredient: query }
  ]
}));
};

  const removeIngredient = data => {
    const results = addIngredients.ingredients.filter(
       e => e.ingredients !== data
    );

   setIngredients(
    {
       ...addIngredients,
       ingredients: results
  });
};
Другие вопросы по тегам