【问题标题】:React pass prop to other component to delete from state arrayReact 将 prop 传递给其他组件以从状态数组中删除
【发布时间】:2017-12-30 04:57:20
【问题描述】:

我正在开发一个待办事项应用程序以了解反应的力量。我创建了 3 个组件,我将在下面向您展示。所以我想从位于另一个组件中的数组状态中删除一个待办事项。

看看我下面的组件。

这是我的 TodoAppComponent:

import AddTodoComponent from '../AddTodoComponent/AddTodoComponent';

class TodoAppComponent extends Component {
  render() {
    return (
        <div id="page-content-wrapper">
            <div className="container">
                <div className="row">
                    <div className="col-lg-6 col-lg-offset-3">
                        <h1 className="m-b-md">What needs to be done?</h1>

                        <AddTodoComponent></AddTodoComponent>
                    </div>                         
                </div>
            </div>
        </div>
    );
  }
}

export default TodoAppComponent;

这里有 TodoItemComponent:

class TodoItemComponent extends Component {
  deleteTodo(todo){
      console.log('deleteTodo', todo);
      this.props.onDelete(this.props.todo);
  }



  render() {
      console.log('this.props.todo', this.props.todo);

return (
    <div>            
        <li className="list-group-item todo-item">
            <button className="btn btn-xs btn-react btn-circle m-r-md">
                <span className="fa fa-check"></span>
            </button>
            {this.props.todo}
            <span className="pull-right">
                <button className="btn btn-xs btn-react btn-circle m-r-xs">
                    <span className="fa fa-pencil-square-o"></span>
                </button>

                <button className="btn btn-xs btn-react btn-circle" onClick={this.deleteTodo.bind(this.props.todo)}>
                    <span className="fa fa-trash-o"></span>
                </button>
            </span>
        </li>
    </div>
);

} }

导出默认TodoItemComponent;

class TodoItemComponent extends Component {
  deleteTodo(){
    // this.setState({
    //   data: update(this.state.data, {$splice: [[index, 1]]})
    // })
    console.log('deleteTodo', this.props.todo);
  }


  render() {      
    console.log(this.props.todo, this.props.title);

    return (
        <div>            
            <li className="list-group-item todo-item">
                <button className="btn btn-xs btn-react btn-circle m-r-md">
                    <span className="fa fa-check"></span>
                </button>
                {this.props.todo}
                <span className="pull-right">
                    <button className="btn btn-xs btn-react btn-circle m-r-xs">
                        <span className="fa fa-pencil-square-o"></span>
                    </button>

                    <button className="btn btn-xs btn-react btn-circle" onClick={this.deleteTodo}>
                        <span className="fa fa-trash-o"></span>
                    </button>
                </span>
            </li>
        </div>
    );
  }
}

export default TodoItemComponent;

这是 AddTodoComponent:

import TodoItemComponent from '../TodoItemComponent/TodoItemComponent';

class AddTodoComponent extends Component {
    constructor(props) {
        super(props);

        this.state = {
            todo: '',
            todoArray: []
        };
    }

    addTodo(e){
        this.setState({ todo: e.target.value });
        this.state.todoArray.push(<TodoItemComponent todo={this.state.todo} onDelete={this.delete}></TodoItemComponent>);
    }

    delete(index){
    //     this.setState({
    //         todoArray: update(this.state.todoArray, {$splice: [[index, 1]]})
    //     });

        console.log('testDelete', this.state.todoArray);
    }

    handleChange(e){
        this.setState({ todo: e.target.value });
    }

    render() {
        return (            
            <div>
                <div className="input-group m-b-md">
                    <input type="text" className="form-control add-todo" placeholder="Todo..." value={this.state.todo} onChange={this.handleChange.bind(this)} />
                    <span className="input-group-btn">
                        <button className="btn btn-react" type="button" onClick={this.addTodo.bind(this)}>Add</button>
                    </span>
                </div>
                <ul className="list-group">
                    {this.state.todoArray}
                </ul>
            </div>
        );
    }
}

export default AddTodoComponent;

如您所见,我尝试在单击删除按钮时记录 this.props.todo,因此当它在 TodoItemComponent 中发出 deleteTodo function 时。它返回给我Uncaught TypeError: Cannot read property 'props' of null 但在render() 方法中它被识别并记录输入的结果。

因此我尝试在TodoItemComponent中的deleteTodo函数中绑定prop:

            <button className="btn btn-xs btn-react btn-circle" onClick={this.deleteTodo.bind(this.props.todo)}>
                <span className="fa fa-trash-o"></span>
            </button>

所以函数看起来像这样:

deleteTodo(todo){
      console.log('deleteTodo', todo);
      this.props.onDelete(this.props.todo);
  }

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 你试过onDelete={() =&gt; this.delete(1)}或其他一些索引吗?
  • 您无法在delete 方法中访问this.props.todo 的值。因此,您必须像 onClick={this.delete.bind(this, this.props.todo)} 那样为其提供上下文。有了这个,您可以在您的 delete 自定义方法中访问待办事项。
  • 您不应该将渲染的 React 组件存储在状态中。将普通的旧 JavaScript 对象和数组存储在状态中,并且仅在 render 中呈现 React 组件。 addTodo 方法将导致渲染组件被推送到在 render 生命周期之外更新的数组中出现问题。
  • @RossAllen 谢谢你会怎么做?
  • @RossAllen 你是这个意思吗?我无法访问delete() 中的this.state.todoArray。它返回给我:uncaught TypeError: Cannot read property 'todoArray' of undefine

标签: javascript reactjs state


【解决方案1】:

您的问题是这里滥用Function.prototype.bind

onClick={this.deleteTodo.bind(this.props.todo)}
//                            ^ you're binding todo as the context

第一个参数应该是绑定函数的上下文,即this,而不是待办事项。

onClick={this.deleteTodo.bind(this)}

并且您应该在deleteTodo 函数中使用this.props.todo(现在具有适当的上下文)。

或者,您可以通过an arrow function(维护它的外部上下文)传递todo

onClick={() => this.deleteTodo(this.props.todo)}

您的deleteTodo 方法将接收todo 作为其第一个参数。

【讨论】:

  • 感谢您的解释,现在我将道具记录在两个组件中。但是当我尝试更新 AddTodoComponent 中的状态时,它会抛出这个错误:uncaught TypeError: Cannot read property 'todoArray' of undefined
  • 在除delete() 之外的所有其他函数中,this.state.todoArray 都被识别,甚至无法记录状态..
【解决方案2】:

将数据存储在 this.state 中,并且只在 render 中创建 React 元素,如下所示:

class AddTodoComponent extends Component {
    constructor(props) {
        super(props);

        this.state = {
            todo: '',
            todoArray: []
        };
    }

    addTodo(e){
        this.state.todoArray.push(e.target.value);
        this.setState({ todo: '' });
    }

    delete(index){
        console.log('testDelete', this.state.todoArray);
    }

    handleChange(e){
        this.setState({ todo: e.target.value });
    }

    render() {
        return (            
            <div>
                <div className="input-group m-b-md">
                    <input type="text" className="form-control add-todo" placeholder="Todo..." value={this.state.todo} onChange={this.handleChange.bind(this)} />
                    <span className="input-group-btn">
                        <button className="btn btn-react" type="button" onClick={this.addTodo.bind(this)}>Add</button>
                    </span>
                </div>
                <ul className="list-group">
                    {this.state.todoArray.map((todo, index) => (
                      <TodoItemComponent todo={todo} onDelete={this.delete.bind(this, index)}></TodoItemComponent>
                    ))}
                </ul>
            </div>
        );
    }
}

【讨论】:

  • 感谢您的回答,但 todo 道具未正确显示,即输入字段的值。
  • 只有在onChange方法被触发时才会出现。
  • 我不太明白你想让它做什么。
  • todo prop 无法正常工作它必须显示在TodoItemComponent 中,如您所见它是输入值。但现在它只在onChange 方法上触发。
  • 所以首先我给了todo prop这个this.state.todo所以它可以在TodoItemComponent中呈现但是当我使用你的代码时我无法访问todo prop所以todoItem返回空。
猜你喜欢
  • 2021-08-15
  • 2021-11-15
  • 2019-09-18
  • 2022-07-15
  • 2019-09-29
  • 2019-01-20
  • 2022-01-18
  • 1970-01-01
  • 2022-01-20
相关资源
最近更新 更多