首页 > 解决方案 > Delete one item in an array ReactJS (React Hooks and Redux)

问题描述

I'm creating a recipe application using MERN stack.

The issue I am stuck on is trying to delete an ingredient found in an array, inside a recipe object. My recipe object looks like this:

MongoDB Recipe Object

Each ingredient has a cross next to it that allows you to click on it to remove.

<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>

The addIngredients and removeIngredient functions look like this:

  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)
);
};

Every time I remove an ingredient from my list I get an error that states "TypeError: Cannot read property 'map' of undefined".

Is there something that i'm missing here? I have been working on this app for the past couple of months now and I am stuck on this particular bit. I thought a better way would be to use Redux as I have been able to delete a whole recipe using a reducer:

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

but how would I be able to target one particular ingredient?

Any suggestions would be greatly appreciated.

标签: reactjsreact-reduxreact-hooksredux-reducers

解决方案


我为您的代码问题添加了注释)

  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)返回过滤的成分而不是带有过滤成分字段的 addIngredients

应该如何

  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
  });
};

推荐阅读