首页 > 解决方案 > 在 React JS 中单击具有特定键的子组件时更改父组件的状态

问题描述

我正在用 React JS 制作一个 Todo 应用程序,我对 React JS 还很陌生。

我制作了两个组件,分别命名为AddComponent组件TodoItem。有AddComponent一个输入和按钮来添加TodoItem待办事项,每当使用AddComponent.

当根据其键单击其中的按钮时,我还必须删除子组件TodoItem,因此它将从父组件的状态中删除该项目AddComponent

我面临的问题是我无法在render()函数之外的任何地方更改状态,因为我在其中TodoItem使用状态动态生成组件。

更改函数内部的状态render()会导致无限循环。请帮助如何解决这个问题。

我正在使用使用 CDN 进行样式设置的 Bootstrap 4。

添加组件.js

import React from 'react'
import shortid from 'shortid'
import TodoItem from './TodoItem';

class AddComponent extends React.Component {
    constructor() {
        super();
        this.state = {
            todoText: '',
            todoList: []
        }
        this.handleChange = this.handleChange.bind(this);
        this.handleClick = this.handleClick.bind(this);
        this.handleTodoClick = this.handleTodoClick.bind(this);
    }
    handleChange(e) {
        e.persist();
        this.setState((prevState) => {
            return {
                todoText: e.target.value,
                todoList: prevState.todoList
            }
        })
    }
    handleClick() {
        this.setState((prevState) => {
            return {
                todoText: prevState.todoText,
                todoList: [{
                    text: prevState.todoText,
                    id: shortid.generate()
                }, ...prevState.todoList]
            }
        })
    }
    handleTodoClick(id) {
        const newState = this.state.todoList.filter(todoL => todoL.id === id);
        this.setState({ todoList: newState });
    }

    render() {
        const todos = this.state.todoList.map((todo) => {
            return (
                <TodoItem key={todo.id} value={todo.text} click={this.handleTodoClick(todo.id)}>{todo.text}</TodoItem>
            )
        })
        return (
            <div>
                <div className="row">
                    <div className="col-sm-9">
                        <div className="form-group">
                            <input
                                type="text"
                                className="form-control"
                                placeholder="Add a Todo"
                                onChange={this.handleChange}
                            />
                        </div>
                    </div>
                    <div className="col-sm-3">
                        <button
                            type="button"
                            className="btn btn-primary btn-block"
                            onClick={this.handleClick}
                        >Add
                        </button>
                    </div>
                </div>
                <div>
                    {todos}
                </div>
            </div>
        )
    }
}

export default AddComponent

TodoItem.js

import React from 'react'

class TodoItem extends React.Component {
    constructor(props) {
        super(props);

    }
    render() {
        return (
            <div className="alert alert-secondary alert-dismissible fade show">
                <button
                    type="button"
                    className="close"
                    onClick={this.props.click}
                    data-dismiss="alert">&times;</button>
                {this.props.value}
            </div>
        )
    }
}

export default TodoItem

标签: reactjs

解决方案


试试:https ://codesandbox.io/s/hopeful-moon-duqfe

有两个问题;第一个是过滤器,第二个是设置为单击道具的处理程序回调函数。

第一个问题:过滤器功能应该过滤与您的 id 不匹配的内容,因此您应该使用 NOT equal :

  handleTodoClick(id) {
    const newState = this.state.todoList.filter(todoL => todoL.id !== id);
    this.setState({ todoList: newState });
  }

第二个问题:当你将 click prop 设置为处理回调函数时,你应该设置函数本身的引用而不调用它。不是这样的:click={this.handleTodoClick(todo.id)。这将调用该函数并将 click 属性设置为它的结果,这是未定义的,因为它不会返回任何内容。

所以我已将您的点击道具更改为click={this.handleTodoClick}

    const todos = this.state.todoList.map(todo => {
      return (
        <TodoItem key={todo.id} id={todo.id} value={todo.text} click={this.handleTodoClick}>
          {todo.text}
        </TodoItem>
      );
    });

在子组件上, onClick 类似地设置为功能本身onClick={() => this.props.click(this.props.id)}NOT like onClick={this.props.click(this.props.id)}

import React from "react";

class TodoItem extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    return (
      <div className="alert alert-secondary alert-dismissible fade show">
        <button
          type="button"
          className="close"
          onClick={() => this.props.click(this.props.id)}
          data-dismiss="alert"
        >
          &times;
        </button>
        {this.props.value}
      </div>
    );
  }
}


推荐阅读