【问题标题】:Setting a checkbox "check" property in React在 React 中设置复选框“检查”属性
【发布时间】:2016-12-31 09:27:24
【问题描述】:

我在使用 React 和复选框时遇到了一个非常烦人的问题。我正在使用的应用程序需要一个复选框列表,这些复选框表示后端保留的设置。 可以选择将设置恢复到原始状态

起初,我创建了一个组件,它有一个像设置地图这样的对象。每个设置都有一个键和一个布尔值。因此:

{
    bubbles: true,
    gregory: false
}

要表示为:

<input type="checkbox" value="bubbles" checked="checked" />
<input type="checkbox" value="gregory" />

现在,React 似乎不知道复选框应该如何工作。我不想设置复选框的值,我想要“checked”属性。

但是,如果我尝试这样的事情:

<input
    type="checkbox"
    value={setting}
    checked={this.settings[setting]}
    onChange={this.onChangeAction.bind(this)}
/>

我收到此警告:

警告:AwesomeComponent 正在更改复选框类型的不受控制的输入以进行控制。输入元素不应从不受控切换到受控(反之亦然)。决定在组件的生命周期内使用受控输入元素还是不受控输入元素。更多信息:[一些无用的文档页面我读了几遍都没用]

所以我决定创建另一个组件来包装每个单独的复选框,我得到了这个:

<input
    type="checkbox"
    checked={this.state.checked}
    onChange={this.onChangeAction.bind(this)}
/>

现在checked 是我所在州直接存在的属性。

这会产生相同的警告,所以我尝试使用defaultChecked

<input
    type="checkbox"
    defaultChecked={this.state.checked}
    onChange={this.onChangeAction.bind(this)}
/>

这使警告消失,但现在无法将checked 值重置为默认值。所以我尝试使用方法componentWillReceiveProps,这样我很确定我的状态是正确的,this.state.checked是正确的并且组件再次渲染。

确实如此。但复选框保持原样。 现在我留下了那个丑陋的警告,我正在使用checked。 我该如何解决这个问题,让警告消失?

我在想也许有一种方法可以强制重新渲染组件,因此它会捕获新的 defaultChecked 值并使用它。但我不知道该怎么做。也许抑制此组件的警告only?那可能吗?也许还有其他可以做的?

【问题讨论】:

    标签: reactjs checkbox default-value


    【解决方案1】:

    基本上,defaultChecked 表示您不想控制输入 - 它只是使用此值呈现,然后无法控制它。此外,不应使用value,而应使用checked,因此您的第二个代码应该是正确的。而且你不应该同时使用它们。

    <input
        type="checkbox"
        checked={this.state.checked}
        onChange={this.onChangeAction.bind(this)}
    />
    

    你能用这种行为创造一个小小提琴吗?

    【讨论】:

    • 他的问题是因为 this.state.checked 是未定义的,而不是 false。所以这样的东西更安全一点:
    【解决方案2】:

    您可以将数据分配给状态,然后使用与单个复选框关联的选中属性将状态设置为

    {   this.state.data.map(function(item, index) {
          return (
            
            <input type="checkbox" checked={item.value} onChange={this.handleChange.bind(this, index)}/>
            
          );
        }.bind(this))
        }
    

    状态中的样本数据为

    data: [{name:'bubbles', value: true}, {name:'gregory', value: false}]
    

    JSFIDDLE

    【讨论】:

      【解决方案3】:

      如果您将复选框的checked 属性设置为nullundefined,则会出现问题。

      这些是 JS 中的“虚假”值,但 React treats a value of null as if the property was not set 根本没有。由于复选框的默认状态未选中,因此一切正常。如果你随后将checked 设置为true,React 认为该属性突然出现了!这是 React 显示你从不受控切换到受控的时候,因为现在存在 checked 属性。

      在您的示例中,您可以通过将 checked={this.settings[setting]} 更改为 checked={!!this.settings[setting]} 来消除此警告。注意双重爆炸(!!)。他们会将nullundefined 转换为false(并留下true),因此React 将使用false 值注册您的checked 属性,并从受控表单组件开始。

      我也有这个问题,我也读了docs about controlled-components 几次都没有用,但我终于弄明白了,所以我想我会分享。此外,由于version 15.2.0 正常输入被触发以通过设置value 来控制,而复选框被初始化为通过设置checked 控制,而不管它们的value 属性如何,这增加了一些混乱。

      【讨论】:

      • 浪费了一个多小时,因为我认为我理解了这个问题,因为 React 发出了非常具体的警告消息。没有。这是一个未定义的变量,后来被定义。谢谢。
      • 我对这个答案赞不绝口。我有条件地添加和删除 checked 属性本身,这在纯 HTML 时代是一种很好的做法。我花了 20 分钟对为什么会出现此错误消息感到困惑。 ReactJS 错误消息确实应该有一个特殊情况,承认 HTML 复选框输入的不一致怪异,这样其他人也不会碰到这个。
      • 令人难以置信的答案 :) 这是一个我不知道的好技巧(使用双键立即转换为布尔值)
      • 我也没有意识到复选框是由“checked”属性而不是“value”控制的。在我找到这篇文章之前,我有一些奇怪的行为。谢谢! reactjs.org/docs/forms.html
      【解决方案4】:

      Amoebe 的回答是正确的,但我认为有比双银行 (!!) 更清洁的解决方案。只需为 Checkbox 组件的 checked 属性添加一个值为 falsedefaultProps 属性:

      import React from 'react';
      
      const Checkbox = ({checked}) => (
        <div>
            <input type="checkbox" checked={checked} />
        </div>
      );
      
      Checkbox.defaultProps = {
        checked: false
      };
      
      export default Checkbox;
      

      【讨论】:

      • 函数声明中只有{checked = false}怎么样?
      • 是的,这对我来说似乎有点矫枉过正
      【解决方案5】:

      如果您选择将类组件转换为功能组件,这里是一个使用钩子的答案...

      export default Checklist = () => {
        const [listOfItems, setListOfItems] = useState([
          {name: 'bubbles', isChecked: true},
          {name: 'gregory', isChecked: false}
        ]);
      
        const updateListOfItems = (itemIndex, newsChecked) => {
          const updatedListOfItems = [...listOfItems];
          updatedListOfItems[itemIndex].isChecked = isChecked;
          setListOfItems(updatedListOfItems);
        }
      
        return (
          {listOfitems.map((item, index) =>
            <index key={index} type="checkbox" checked={item.isChecked} onChange={() => updateListOfItems(index, !item.isChecked)} />
          )}
        )
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-27
        • 2017-01-06
        • 2018-01-10
        相关资源
        最近更新 更多