React传递prop到其他组件以从状态数组中删除

时间:2017-07-24 14:38:54

标签: javascript reactjs state

我正在研究todo应用程序,以了解反应的力量。我创建了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);
  }

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

2 个答案:

答案 0 :(得分:2)

您的问题是此处误导Function.prototype.bind

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

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

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

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

或者,您可以an arrow function(维护其外部背景)传递todo

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

并且您的deleteTodo方法会收到todo作为其第一个参数。

答案 1 :(得分:1)

将数据存储在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>
        );
    }
}