无法正确使用复选框来更新状态

时间:2016-02-23 18:03:02

标签: reactjs

我正在使用一个复选框,该复选框应通过组件的状态更新待办事项的已完成状态。当我点击待办事项框时,它不会改变状态,但如果我点击它两次,它会更新状态。由于我必须单击两次,这意味着当选中此框时,this.state.done === false以及取消选中this.state.done === true。我不知道为什么它不会在第一次点击时翻转状态。该复选框由 handleDoneChange()控制。有人可以告诉我为什么复选框不会在第一次点击时改变状态吗?

class ShowTodo extends Component {

    static contextTypes = {
        router: PropTypes.object
    };

    constructor(props) {
        super(props);

        this.state = {
            descriptionChanged: false,
            newDescription: '',
            newTitle: '',
            done: false
        };


        this.handleDescriptionChange = this.handleDescriptionChange.bind(this);
        this.handleDeleteClick = this.handleDeleteClick.bind(this);
        this.changeButtons = this.changeButtons.bind(this);
        this.handleSaveClick = this.handleSaveClick.bind(this);
        this.handleUndoClick = this.handleUndoClick.bind(this);
        this.handleTitleChange = this.handleTitleChange.bind(this);
        this.handleDoneChange = this.handleDoneChange.bind(this);
    }

    componentWillMount() {
        this.props.fetchTodo(this.props.params.id).then(() => {
            this.setState({
                newDescription: this.props.todo.description,
                newTitle: this.props.todo.title,
                done: this.props.todo.completed
            });
            console.log("This is the todo's starting completed status: ", this.state.done);
        });
    }

    render() { 

        const { todo } = this.props;

        if (!todo) {
            return (
                <h3>Loading...</h3>
            );
        }

        return (
            <div className="input-group">
                <Link to="/todos_index">Back</Link>
                <h3>Title</h3>
                <input 
                    type="text" 
                    className="form-control"
                    value={this.state.newTitle}
                    onChange={this.handleTitleChange} />
                <textarea 
                    className="form-control" 
                    value={this.state.newDescription}
                    onChange={this.handleDescriptionChange}>
                </textarea>
                <span className="input-group-addon">
                    <input type="checkbox"
                      onClick={this.handleDoneChange} />
                </span>
                <span className="input-group-btn">
                    {this.changeButtons()}
                    <button onClick={this.handleDeleteClick} className="btn btn-danger pull-xs-right">Delete Post</button>
                </span>


            </div>
        );
    }

    changeButtons() {
        if (!this.state.descriptionChanged) {
            return null;
        } else {

            return [
            <button 
              className="btn btn-default"
              onClick={this.handleSaveClick}
              >Save</button>,
            <button 
              className="btn btn-default"
              onClick={this.handleUndoClick}
              >Undo</button>
           ];
        }
    }

    handleDescriptionChange(event) {
        this.setState({
            descriptionChanged: true,
            newDescription: event.target.value
        });
        console.log('New description in state: ', this.state.newDescription);
    }

    handleTitleChange(event) {
        this.setState({
            descriptionChanged: true,
            newTitle: event.target.value
        });
    }

    handleDoneChange(event) { //This isn't updating the done status

        this.setState({
            done: !this.state.done
        });

        var id = this.props.params.id;

        var props = {
            completed: this.state.done
        };

        console.log(props);

        this.props.updateTodo(id, JSON.stringify(props));

    }

    handleDeleteClick(event) {
        this.props.deleteTodo(this.props.params.id).then(() => {
            this.context.router.push('/todos_index');
        });
    }

    handleSaveClick(event) {
        var id = this.props.params.id;
        var props = {
            title: this.state.newTitle,
            description: this.state.newDescription
        };
        this.props.updateTodo(id, JSON.stringify(props)).then(() => {
            this.context.router.push('/todos_index');
        });
    }

    handleUndoClick() {
        this.setState({
            descriptionChanged: false,
            newTitle: this.props.todo.title,
            newDescription: this.props.todo.description

        });
    }
}

function mapStateToProps(state) {
    return { todo: state.todos.todo };
}

export default connect(mapStateToProps, { fetchTodo, updateTodo, deleteTodo })(ShowTodo);

1 个答案:

答案 0 :(得分:2)

复选框应使用onChange而不是onClick

编辑:还有另一个问题。

您的组件工作正常。您的调试console.log不是。

this.setState是异步的,因此您不会在以下代码行中看到更改。如果您想在状态更改完后执行某些操作,则应将其作为回调传递给setState函数:

this.setState({
        descriptionChanged: true,
        newDescription: event.target.value
    }, function(){         
           console.log('New description in state: ', this.state.newDescription);
    }
});