React.js无法更改复选框状态。

39

我创建了这个简单的待办事项列表,但当我想要勾选复选框时却无法操作。

import React from 'react';

const TodoItem = React.createClass({

  render() {
    return (
      <div>

        <span>{this.props.todo}</span>
        <input type="checkbox" checked={this.props.done} />

      </div>
    );
  }

});

export default TodoItem;

父元素:

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

const TodoList = React.createClass({

  getInitialState() {
    return {
      todos: [{
        todo: 'some text',
        done:false
      },{
        todo: 'some text2',
        done:false
      },
      {
        todo: 'some text3',
        done:true
      }]
    };
  },

   addTodo (childComponent) {
    var todoText = childComponent.refs.todoText.getDOMNode().value;
    var todo = {
      todo: todoText,
      done:false
    };
    var todos = this.state.todos.concat([todo]);
    this.setState({
      todos:todos
    });

    childComponent.refs.todoText.getDOMNode().value = '';
  },

  render() {

    var Todos = this.state.todos.map(function(todo) {
      return (
           <TodoItem todo={todo.todo} done={todo.done} />
        )
    });

    return (
      <div>
       {Todos}
       <AddTodo addTodo={this.addTodo}/>
      </div>

    );
  }

});

export default TodoList;
3个回答

44

当你未在输入框中指定 onChange 处理程序时,React 将将该输入框渲染为只读状态。

getInitialState() {
    return {
        done: false
    };
}

<input type="checkbox" checked={this.state.done || this.props.done } onChange={this.onChange} />

7
为什么我需要这样做?我不需要onChange处理程序,我需要在此处理程序内编写什么内容? - Bazinga
5
React需要它,因为输入框必须是“受控”或“不受控”的一种。请阅读此处的文档了解详情:http://facebook.github.io/react/docs/forms.html - Henrik Andersson
您不需要一个onChange处理程序。不提供它也不会使该字段“只读”。 - Chris
@Chris 请看下面我的回答。在运行下面的JSBin时,似乎对我来说确实会呈现出只读复选框。JSBin - BenjiFB
此外,添加onChange处理程序似乎并没有使其工作。仍然似乎是只读的:[JSBin](http://jsbin.com/royofagova/1/edit?js,output),除非在上面的示例中我误解了并且确实应该实现此功能? - BenjiFB
显示剩余2条评论

9

对于其他人的参考,React现在提供了defaultChecked属性:

<label htmlFor={id}>
  <input
    id={id}
    type="checkbox"
    defaultChecked={input.props.checked}
    // disabled={input.props.disabled}
  />
  <span className="custom-checkbox"></span>
  {restChildren}
</label>

将 "checked" 更改为 "defaultChecked" 对我解决了问题。谢谢! - Eric Antoine Scuccimarra

7
这是在谷歌上搜索“React组件不更新”时排名靠前的答案之一,虽然答案被广泛接受,但我认为它可能会产生误导。对于checkbox类型而言,不需要onChange处理程序。 我不确定自从发布此答案以来(React的当前版本为v15-2016-04-20)是否发生了更改。
请查看以下示例,演示了在没有onChange处理程序的情况下它的工作方式(请参见JSBIN):
class Checky extends React.Component {
    render() {
      return (<input type="checkbox" checked={this.props.checked} />);
    }
}

class App extends React.Component {

    constructor(props) {
        super(props);
        this.state = { checked: true };
    }

    render() {
        return (
          <div>
            <a href="#" onClick={ () => { this.setState({ checked: !this.state.checked }); }}>Toggle</a>
            <hr />
            <Checky checked={this.state.checked} />
          </div>
        );
    }
}


React.render(<App />, document.body);

另外需要注意的是,在类似问题的很多回答中,只建议使用"defaultChecked" - 尽管这有效,但通常只是半吊子解决办法。


上面的答案表明,如果没有"OnChanged"处理程序,复选框将被呈现为只读。当我点击你的JSBin时,我看到的确切行为就是:当我点击复选框本身(而不是链接)时,选中状态不会发生任何变化。这是您的期望吗? - BenjiFB
是的。我的观点是,“onChange”并不是使其成为可编辑(非只读)组件所必需的。您如何触发该状态更改(无论是通过复选框onClick / onChange),这取决于您。 - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接