从子组件中处于状态的数组中删除项目

时间:2019-02-23 13:35:25

标签: javascript reactjs

尝试通过点击处理程序从我的状态下的餐食数组中删除一项,但该项目无法正常工作。我还看到了将第二个参数传递给.map函数的其他示例,但Meal.js中没有.map。我可能可以通过将Meal.js HTML移到MealList.js中来解决此问题,但我想通过将它们分开来保持代码更整洁。

要实现此目标,我缺少什么?现在,当我单击X按钮删除该项目时,它会删除除一个项目以外的所有项目。

App.js:

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            meals: []
        };
        this.removeMeal = this.removeMeal.bind(this);
    }


    componentDidMount() {
        const meals = [
            {
                id: 1,
                name: "Test one",
                ingredients: [
                    "stuff 1",
                    "stuff 2"
                ]
            },
            {
                id: 2,
                name: "Test two",
                ingredients: [
                    "stuff 1",
                    "stuff 2"
                ]
            },
        ];

        this.setState({
            meals: meals
        });
    }

    removeMeal(e) {
        const meals = this.state.meals;
        const index = meals.indexOf(e.target);
        const newMeals = meals.splice(index, 1);
        this.setState({
            meals: newMeals
        });
    }

    render() {
        return (
            <section>
                <Router>
                    <MealList
                        path="/"
                        meals={this.state.meals}
                        removeMeal={this.removeMeal}
                    />
                </Router>
            </section>
        );
    }

MealList.js:

class MealList extends Component {
    render() {
        return (
            <div>
                <ul className="meal-list">
                    {this.props.meals.map((meal, i) => {
                        return (
                            <Meal
                                name={meal.name}
                                ingredients={meal.ingredients}
                                key={meal.id}
                                removeMeal={this.props.removeMeal}
                            />
                        );
                    })}
                </ul>
            </div>
        );
    }
}

Meal.js:

class Meal extends Component {

    render() {
        return (
            <li>
                <h2>{this.props.name}</h2>
                <ul className="ingredient-list">
                    {this.props.ingredients.map(item => {
                        return <li key={item}>{item}</li>;
                    })}
                </ul>

                <button type="button" className="remove-recipe" onClick={() => this.props.removeMeal(this.props.name)}>
                    &times;
                </button>
            </li>
        );
    }
}

1 个答案:

答案 0 :(得分:4)

您将name的餐食e传递到您的removeMeal方法中。由于e.target将是undefined,因此您将始终使用splice(-1, 1)删除数组的最后一个元素。

您可以改用数组方法filter并通过传递给name方法的removeMeal过滤出对象。

removeMeal = name => {
  this.setState(prevState => {
    const meals = prevState.meals.filter(meal => meal.name !== name);
    return { meals };
  });
};

class App extends React.Component {
  state = {
    meals: [
      {
        id: 1,
        name: "Test one",
        ingredients: ["stuff 1", "stuff 2"]
      },
      {
        id: 2,
        name: "Test two",
        ingredients: ["stuff 1", "stuff 2"]
      }
    ]
  };

  removeMeal = name => {
    this.setState(prevState => {
      const meals = prevState.meals.filter(meal => meal.name !== name);
      return { meals };
    });
  };

  render() {
    return (
      <section>
        <MealList
          path="/"
          meals={this.state.meals}
          removeMeal={this.removeMeal}
        />
      </section>
    );
  }
}

class MealList extends React.Component {
  render() {
    return (
      <div>
        <ul className="meal-list">
          {this.props.meals.map((meal, i) => {
            return (
              <Meal
                name={meal.name}
                ingredients={meal.ingredients}
                key={meal.id}
                removeMeal={this.props.removeMeal}
              />
            );
          })}
        </ul>
      </div>
    );
  }
}

class Meal extends React.Component {
  render() {
    return (
      <li>
        <h2>{this.props.name}</h2>
        <ul className="ingredient-list">
          {this.props.ingredients.map(item => {
            return <li key={item}>{item}</li>;
          })}
        </ul>

        <button
          type="button"
          className="remove-recipe"
          onClick={() => this.props.removeMeal(this.props.name)}
        >
          &times;
        </button>
      </li>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>