警告: 在<select>标签上使用“defaultValue”或“value”属性代替在<option>标签上设置“selected”。

155

场景:用户有一个下拉框,他选择一个选项。我希望显示该下拉框并将上次被该用户选择的选项作为默认值。

我在选项上使用了selected 属性,但React提示我在select标签上使用default value属性。

例如:

render: function() {
    let option_id = [0, 1];
    let options = [{name: 'a'}, {name: 'b'}];
    let selectedOptionId = 0

    return (
      <select defaultValue={selectedOptionId}>
        {option_id.map(id =>
        <option key={id} value={id}>{options[id].name}</option>
        )}
      </select>
    )
  }
});

问题是我不知道 selectedOptionId,因为选定的选项可以是任何选项。如何找到 defaultValue

10个回答

143
React使用value代替selected以保持表单组件的一致性。您可以使用defaultValue设置初始值。如果您正在控制值, 您也应该设置value。否则,不要设置value,而是处理onChange事件以对用户操作做出反应。 注意valuedefaultValue应与选项的value匹配。

3
我在<select>元素上使用了"value"属性,而不是defaultValue,正如你所说,我将"value"属性的值保持一致,既用于<option>选项也用于<select>。这样,它就起作用了! 谢谢。 - Piyush
4
如果我使用“value”来设置选中的选项,但是我选择了其他选项,选择框并没有更改选项的值。 :( - huykon225
你需要在SELECT元素上设置“value”,它就可以工作了! - s2t2
我们可以使用value或defaultValue来设置初始值。 - Avan
defaultValue 对我没用。 - Arindam Sarkar
显示剩余2条评论

132
在您想要设置占位符而不选择默认值的情况下,您可以使用此选项。
      <select defaultValue={'DEFAULT'} >
        <option value="DEFAULT" disabled>Choose a salutation ...</option>
        <option value="1">Mr</option>
        <option value="2">Mrs</option>
        <option value="3">Ms</option>
        <option value="4">Miss</option>
        <option value="5">Dr</option>
      </select>

用户被强制选择一个选项!

编辑

如果这是受控组件

在这种情况下,不幸的是,您将不得不使用defaultValue和value来违反React的某些规则。这是因为react根据语义不允许将禁用的值设置为活动状态。

 function TheSelectComponent(props){
     let currentValue = props.curentValue || "DEFAULT";
     return(
      <select value={currentValue} defaultValue={'DEFAULT'} onChange={props.onChange}>
        <option value="DEFAULT" disabled>Choose a salutation ...</option>
        <option value="1">Mr</option>
        <option value="2">Mrs</option>
        <option value="3">Ms</option>
        <option value="4">Miss</option>
        <option value="5">Dr</option>
      </select>
    )
}

18
注意,由于您的默认选项 <option value="DEFAULT" disabled>选择称谓...</option> 具有真值,如果将此选择输入标记为必需,则默认表单验证不会捕获其值。考虑使用空字符串 "" 代替。 - brettinternet
1
用户不一定需要同时使用两者。如果将禁用选项的值设置为非真值,例如 "",并将该值作为defaultValue或value传递给select,则可以将其用作活动占位符。 - Avan

14

您可以在构造函数中设置this.state的属性,使其成为<select>标签上的selected属性。这样,您设置的初始值(默认值)以及下拉菜单更改时需要更改状态。

constructor(){
  this.state = {
    selectedId: selectedOptionId
  }
}

dropdownChanged(e){
  this.setState({selectedId: e.target.value});
}

render(){
  return(
    <select value={this.selectedId} onChange={this.dropdownChanged.bind(this)}>
      {option_id.map(id =>
        <option key={id} value={id}>{options[id].name}</option>
      )}
    </select>
  );
}

请使用“defaultValue”代替“selected”属性。 - user1742302

7
感谢您们的讨论!我和我的同事刚刚发现,default_value属性是一个常量,而不是变量。
在我建立的其他React表单中,Select的默认值是在关联的Context中预设的。因此,第一次渲染Select时,default_value被设置为正确的值。
但是在我的最新的React表单(一个小型模态框)中,我通过props传递表单的值,然后使用useEffect来填充相关的Context。因此,在第一次渲染Select时,default_value被设置为null。然后当Context被填充并且Select应该重新渲染时,default_value无法更改,因此初始默认值未被设置。
解决方案最终很简单:使用value属性。但是弄清楚为什么default_value不能像其他表单那样工作需要一些时间。
我发布这篇文章是为了帮助社区中的其他人。

你好,我遇到了同样的问题,你能提供一个这个问题的例子吗?我已经尝试使用value,但是问题仍然存在。 - Developer

7

可以按如下方式使用defaultValue和onChange:

const [myValue, setMyValue] = useState('');

<select onChange={(e) => setMyValue(e.target.value)} defaultValue={props.myprop}>
                    
       <option>Option 1</option>
       <option>Option 2</option>
       <option>Option 3</option>

</select>

Example https://codesandbox.io/s/priceless-lamarr-fetpr?file=/src/App.js


3
要获得 e.target.value,您不也需要在 option 中设置 value 吗? - CodeFinity
@CodeFinity,不需要。你可以在这里查看 https://codesandbox.io/s/priceless-lamarr-fetpr?file=/src/App.js - Sandeep Amarnath
1
@CodeInfinity,这并不是必需的,因为select标签中的onChange属性本来就是用来跟踪选项的。 - Sandeep Amarnath

2

使用Hooks和useState

使用defaultValue来选择默认值。

    const statusOptions = [
        { value: 1, label: 'Publish' },
        { value: 0, label: 'Unpublish' }
    ];
    const [statusValue, setStatusValue] = useState('');
    const handleStatusChange = e => {
        setStatusValue(e.value);
    }

return(
<>
<Select options={statusOptions} 
    defaultValue={[{ value: published, label: published == 1 ? 'Publish' : 'Unpublish' }]} 
    onChange={handleStatusChange} 
    value={statusOptions.find(obj => obj.value === statusValue)} required />
</>
)

1
一种简单的解决方案是在不使用选项中选择值,按照以下步骤操作:
将默认值设置为0(我不考虑其作为要使用的值)x-column 参考图片 enter image description here 4个步骤
  1. x-column的“IntialValue”设置为: 0
  2. 使用与您的[selected]相同的字符串,并在此处设置if条件,并在找到时标记“values.x-column = 0
  3. 删除标签中设置的“selected”和其他项目(如果有) 4.最后设置此条件
现在导航,列中的值默认为在步骤2中标记的值/您想要设置为选定值。
我已经尝试过了,对我有效。

有一个小修正...在图片的第45行中...将该列读作column_value_id


0

从选项中,你应该使用 defaultValue 而不是 value 来自那个选择框的选项:

<select className="form-control text-align:center" onChange={handleChangeCountry}>
            <option type="others" >Select a Country</option>
            {users?.length > 0 && users.map(item => {
              return (<option selected={item.country_name === countryName} key={item.country_id} defaultValue={item.country_id} >
                {item.country_name}
              </option>)
            })}
          </select>


0

我尝试了不同的选项来避免控制台错误,以下选项在选择某些选项时没有控制台错误:

    {const [myValue, setMyValue] = useState('');  
  const changeHandler = (e) => {
    setMyValue(e.target.value);
  };
<select id="select" value={myValue} onChange={changeHandler}>
            {!myValue&& <option value="">choise from list</option>}
            {elementsArr.map((el) => {
              return (
                <option key={el.id} value={el.name}>
                  {el.name}</option>
              );
            })
          </select>}

0

如上所建议,使用defaultValue <select

          <option>Please select</option>
          {categories.length > 0 &&
            categories.map((c) => (
              <option
                key={c._id}
                defaultValue={c._id}
                selected={c._id === parent}>
                {c.name}
              </option>
            ))}
        </select>

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