React JSX: select "selected"选择<选项

<select>菜单的React组件中,我需要在反映应用程序状态的选项上设置selected属性。

render()中,optionState从状态所有者传递给SortMenu组件。选项值作为props从JSON中传入。

render: function() {
var options = [],
optionState = this.props.optionState;


this.props.options.forEach(function(option) {
var selected = (optionState === option.value) ? ' selected' : '';


options.push(
<option value={option.value}{selected}>{option.label}</option>
);
});


// pass {options} to the select menu jsx

但是这会在JSX编译时触发语法错误。

这样做可以避免语法错误,但显然不能解决问题:

var selected = (optionState === option.value) ? 'selected' : 'false';


<option value={option.value} selected={selected}>{option.label}</option>

我还试过这个:

var selected = (optionState === option.value) ? true : false;


<option value={option.value} {selected ? 'selected' : ''}>{option.label}</option>

有没有解决这个问题的推荐方法?

738892 次浏览

React让你更容易做到这一点。不是在每个选项上定义selected,而是你可以(也应该)简单地在选择标签上写value={optionsState}:

<select value={optionsState}>
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>

更多信息,见React选择标签doc

此外,React会自动理解布尔值,所以你可以简单地编写(注:不推荐)

<option value={option.value} selected={optionsState == option.value}>{option.label}</option>

它会适当地输出" selected "

当你试图设置<option>的“selected”属性时,你可以做React警告你的事情:

<select>上使用defaultValuevalue道具,而不是在<option>上设置selected

所以,你可以在选择的defaultValue上使用options.value

我有一个问题,<select>标签没有更新到正确的<option>时,状态改变。我的问题似乎是,如果你连续渲染两次,第一次没有预先选择<option>,但第二次有一个,那么<select>标签不会在第二次渲染时更新,而是首先保持默认值。

我使用参考文献找到了一个解决方案。您需要获得对<select>标记节点(可能嵌套在某些组件中)的引用,然后在componentDidUpdate钩子中手动更新该节点上的value属性。

componentDidUpdate(){
let selectNode = React.findDOMNode(this.refs.selectingComponent.refs.selectTag);
selectNode.value = this.state.someValue;
}
***Html:***
<div id="divContainer"></div>


var colors = [{ Name: 'Red' }, { Name: 'Green' }, { Name: 'Blue' }];
var selectedColor = 'Green';


ReactDOM.render(<Container></Container>, document.getElementById("divContainer"));


var Container = React.createClass({
render: function () {
return (
<div>
<DropDown data={colors} Selected={selectedColor}></DropDown>
</div>);
}
});


***Option 1:***
var DropDown = React.createClass(
{
render: function () {
var items = this.props.data;
return (
<select value={this.props.Selected}>
{
items.map(function (item) {
return <option value={item.Name }>{item.Name}</option>;
})
}
</select>);
}
});


***Option 2:***
var DropDown = React.createClass(
{
render: function () {
var items = this.props.data;
return (
<select>
{
items.map(function (item) {
return <option value={item.Name} selected={selectedItem == item.Name}>{item.Name}</option>;
})
}
</select>);
}
});


***Option 3:***
var DropDown = React.createClass(
{
render: function () {
var items = this.props.data;
return (
<select>
{
items.map(function (item) {


if (selectedItem == item.Name)
return <option value={item.Name } selected>{item.Name}</option>;
else
return <option value={item.Name }>{item.Name}</option>;
})
}
</select>);
}
});

针对MULTISELECT / optgroups发布类似的答案:

render() {
return(
<div>
<select defaultValue="1" onChange={(e) => this.props.changeHandler(e.target.value) }>
<option disabled="disabled" value="1" hidden="hidden">-- Select --</option>
<optgroup label="Group 1">
{options1}
</optgroup>
<optgroup label="Group 2">
{options2}
</optgroup>
</select>
</div>
)
}

下面是一个完整的解决方案,包含了最佳答案和下面的评论(这可能会帮助那些挣扎着把它们拼凑在一起的人):

UPDATE FOR ES6(2019) -使用箭头函数和对象解构

在主要组成部分:

class ReactMain extends React.Component {


constructor(props) {
super(props);
this.state = { fruit: props.item.fruit };
}


handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
}


saveItem = () => {
const item = {};
item.fruit = this.state.fruit;
// do more with item object as required (e.g. save to database)
}


render() {
return (
<ReactExample name="fruit" value={this.state.fruit} handleChange={this.handleChange} />
)
}


}

所包含的组件(现在是一个无状态函数):

export const ReactExample = ({ name, value, handleChange }) => (
<select name={name} value={value} onChange={handleChange}>
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>
)

之前的答案(使用绑定):

在主要组成部分:

class ReactMain extends React.Component {


constructor(props) {
super(props);
// bind once here, better than multiple times in render
this.handleChange = this.handleChange.bind(this);
this.state = { fruit: props.item.fruit };
}


handleChange(event) {
this.setState({ [event.target.name]: event.target.value });
}


saveItem() {
const item = {};
item.fruit = this.state.fruit;
// do more with item object as required (e.g. save to database)
}


render() {
return (
<ReactExample name="fruit" value={this.state.fruit} handleChange={this.handleChange} />
)
}


}

所包含的组件(现在是一个无状态函数):

export const ReactExample = (props) => (
<select name={props.name} value={props.value} onChange={props.handleChange}>
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>
)

主组件维护fruit的选中值(处于状态),被包含的组件显示select元素并将更新传递回主组件以更新其状态(然后循环回被包含的组件以更改所选值)。

请注意,使用了名称道具,它允许您为同一表单上的其他字段声明一个handleChange方法,而不管它们的类型是什么。

简单地添加作为选择标签的第一个选项:

<option disabled hidden value=''></option>

这将成为默认值,当您选择一个有效的选项将设置在您的状态

下面是如何做到这一点的最新例子。从反应文档开始,加上自动绑定的“肥箭头”方法语法。

class FlavorForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'coconut'};
}


handleChange = (event) =>
this.setState({value: event.target.value});


handleSubmit = (event) => {
alert('Your favorite flavor is: ' + this.state.value);
event.preventDefault();
}


render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Pick your favorite flavor:
<select value={this.state.value} onChange={this.handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
</label>
<input type="submit" value="Submit" />
</form>
);
}
}

我通过设置defaultProps解决了一个类似的问题:

ComponentName.defaultProps = {
propName: ''
}

# EYZ0

所以现在,如果我的道具在安装之前不存在,我可以避免在编译时出错。

我有一个简单的解决方案是遵循HTML基本。

<input
type="select"
defaultValue=""
>
<option value="" disabled className="text-hide">Please select</option>
<option>value1</option>
<option>value1</option>
</input>

.text-hide是一个bootstrap的类,如果你不使用bootstrap,这里是:

.text-hide {
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}

使用React 16.8。我们可以像下面的例子一样使用钩子来实现这一点

code andbox link

import React, { useState } from "react";
import "./styles.css";


export default function App() {
const options = [
"Monty Python and the Holy Grail",
"Monty Python's Life of Brian",
"Monty Python's The Meaning of Life"
];
const filmsByTati = [
{
id: 1,
title: "Jour de fête",
releasedYear: 1949
},
{
id: 2,
title: "Play time",
releasedYear: 1967
},
{
id: 3,
releasedYear: 1958,
title: "Mon Oncle"
}
];
const [selectedOption, setSelectedOption] = useState(options[0]);
const [selectedTatiFilm, setSelectedTatiFilm] = useState(filmsByTati[0]);
return (
<div className="App">
<h1>Select Example</h1>
<select
value={selectedOption}
onChange={(e) => setSelectedOption(e.target.value)}
>
{options.map((option) => (
<option key={option} value={option}>
{option}
</option>
))}
</select>
<span>Selected option: {selectedOption}</span>


<select
value={selectedTatiFilm}
onChange={(e) =>
setSelectedTatiFilm(
filmsByTati.find(film => (film.id == e.target.value))
)
}
>
{filmsByTati.map((film) => (
<option key={film.id} value={film.id}>
{film.title}
</option>
))}
</select>
<span>Selected option: {selectedTatiFilm.title}</span>
</div>
);
}

使用defaultValue预选Select的值。

<Select defaultValue={[{ value: category.published, label: 'Publish' }]} options={statusOptions} onChange={handleStatusChange} />

我正在为语言选择器制作下拉菜单-但我需要下拉菜单在页面加载时显示当前语言。我要么从URL参数example.com?user_language=fr中获取我的初始语言,要么从用户的浏览器设置中检测它。然后,当用户与下拉菜单交互时,所选语言将被更新,语言选择器下拉菜单将显示当前所选语言。

因为这整篇文章都在举水果的例子,所以我为你准备了各种水果的好处。

  • 首先,用一个基本的React功能组件回答最初提出的问题——两个带和不带道具的例子,然后如何将组件导入到其他地方。

  • 接下来,同样的例子-但与Typescript的果汁。

  • 一个使用Typescript的语言选择器下拉组件。


基本React(16.13.1)功能组件示例。FruitSelectDropdown的两个例子,一个没有道具&一个是接受道具fruitDetector

import React, { useState } from 'react'


export const FruitSelectDropdown = () => {
const [currentFruit, setCurrentFruit] = useState('oranges')
  

const changeFruit = (newFruit) => {
setCurrentFruit(newFruit)
}
  

return (
<form>
<select
onChange={(event) => changeFruit(event.target.value)}
value={currentFruit}
>
<option value="apples">Red Apples</option>
<option value="oranges">Outrageous Oranges</option>
<option value="tomatoes">Technically a Fruit Tomatoes</option>
<option value="bananas">Bodacious Bananas</option>
</select>
</form>
)
}

或者你可以让FruitSelectDropdown接受道具,也许你有一个输出字符串的函数,你可以使用fruitDetector道具来传递它

import React, { useState } from 'react'


export const FruitSelectDropdown = ({ fruitDetector }) => {
const [currentFruit, setCurrentFruit] = useState(fruitDetector)
  

const changeFruit = (newFruit) => {
setCurrentFruit(newFruit)
}
  

return (
<form>
<select
onChange={(event) => changeFruit(event.target.value)}
value={currentFruit}
>
<option value="apples">Red Apples</option>
<option value="oranges">Outrageous Oranges</option>
<option value="tomatoes">Technically a Fruit Tomatoes</option>
<option value="bananas">Bodacious Bananas</option>
</select>
</form>
)
}

然后导入FruitSelectDropdown到你的应用程序的其他地方

import React from 'react'
import { FruitSelectDropdown } from '../path/to/FruitSelectDropdown'


const App = () => {
return (
<div className="page-container">
<h1 className="header">A webpage about fruit</h1>
<div className="section-container">
<h2>Pick your favorite fruit</h2>
<FruitSelectDropdown fruitDetector='bananas' />


</div>
</div>
)
}


export default App

FruitSelectDropdown与Typescript

import React, { FC, useState } from 'react'


type FruitProps = {
fruitDetector: string;
}


export const FruitSelectDropdown: FC<FruitProps> = ({ fruitDetector }) => {
const [currentFruit, setCurrentFruit] = useState(fruitDetector)
  

const changeFruit = (newFruit: string): void => {
setCurrentFruit(newFruit)
}
  

return (
<form>
<select
onChange={(event) => changeFruit(event.target.value)}
value={currentFruit}
>
<option value="apples">Red Apples</option>
<option value="oranges">Outrageous Oranges</option>
<option value="tomatoes">Technically a Fruit Tomatoes</option>
<option value="bananas">Bodacious Bananas</option>
</select>
</form>
)
}

然后导入FruitSelectDropdown到你的应用程序的其他地方

import React, { FC } from 'react'
import { FruitSelectDropdown } from '../path/to/FruitSelectDropdown'


const App: FC = () => {
return (
<div className="page-container">
<h1 className="header">A webpage about fruit</h1>
<div className="section-container">
<h2>Pick your favorite fruit</h2>
<FruitSelectDropdown fruitDetector='bananas' />


</div>
</div>
)
}


export default App

奖励轮:翻译下拉菜单与选定的当前值:

import React, { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'


export const LanguageSelectDropdown: FC = () => {
const { i18n } = useTranslation()
const i18nLanguage = i18n.language
const [currentI18nLanguage, setCurrentI18nLanguage] = useState(i18nLanguage)
  

const changeLanguage = (language: string): void => {
i18n.changeLanguage(language)
setCurrentI18nLanguage(language)
}
  

return (
<form>
<select
onChange={(event) => changeLanguage(event.target.value)}
value={currentI18nLanguage}
>
<option value="en">English</option>
<option value="de">Deutsch</option>
<option value="es">Español</option>
<option value="fr">Français</option>
</select>
</form>
)
}

React/Typescript的无价资源

如果你使用无状态,那么

const IndexPage =({states, selectedState}) => {
return(
<select id="states" defaultValue={selectedState} name="state">
{states.map(state=> (
<option value={state.id} key={state.id}>{state.name}</option>
))
}
</select>
)
}
if you store objects in a state.


class Studentinformation extends Component
{
constructor(props)
{
super(props);
this.handlechange=this.handlechange.bind(this);
this.handleSubmit=this.handleSubmit.bind(this);
   

this.state={Studentinfo:{
Name:'',
Skill:'Java',
Address:''
}};
}
handlechange(event)
{
const name=event.target.name;
const value=event.target.value;


this.setState({ Studentinfo:
{
...this.state.Studentinfo,
[name]:[value]
}});
}
handleSubmit(event)
{
event.preventDefault();
}
render(){
return (
<div>
<form onSubmit={this.handleSubmit}>
<label>Name: <input type="text" name="Name" value={this.state.Studentinfo.Name} onChange={this.handlechange}></input></label>
<br/>
<label>Skills:
<select value={this.state.Studentinfo.Skill} name="Skill" onChange={this.handlechange}>
<option value="C++" >C++</option>
<option value="C#">C#</option>
<option  value="Java">Java</option>
</select>
</label>
<br/>
<textarea value={this.state.Studentinfo.Address} onChange={this.handlechange}/>
<br/>
<input type="submit" value="Submit"></input>
</form>
</div>
);
}


}

主点控制组件

您正在寻找建立一个“受控组件”。这将要求您在元素上设置值,并处理on change事件以更新值。

https://reactjs.org/docs/forms.html#controlled-components

例子

< a href = " https://codepen。io / codyswartz /钢笔/ QWqYNrY noreferrer“rel = > https://codepen.io/codyswartz/pen/QWqYNrY < / >

简单功能组件选择示例

这还包括一个默认值和灰色。

const defaultSelectValue = "Select a fruit"


const SelectExample = () => {
const [selected, setSelected] = useState(defaultSelectValue)


return (
<>
<label htmlFor="fruits">Fruits</label>{' '}
<select
id="fruits"
name="fruits"
defaultValue={selected}
style=\{\{ color: selected === defaultSelectValue ? "gray" : "black" }}
onChange={e => setSelected(e.target.value)}
>
<option>{defaultSelectValue}</option>
<option>Banana</option>
<option>Apple</option>
<option>Orange</option>
</select>


<h2>Selected: {selected}</h2>
</>
)
}


// Usage
<SelectExample />

带有默认值的动态可重用示例

这将接受一个字符串集合,并将第一个字符串作为默认值。

const SelectExample = ({ name, items }) => {
const defaultSelectValue = items[0]
const [selected, setSelected] = useState(defaultSelectValue)


return (
<>
<label htmlFor={name}>{name}</label>{' '}
<select
id={name}
name={name}
defaultValue={selected}
style=\{\{ color: selected === defaultSelectValue ? "gray" : "black" }}
onChange={e => setSelected(e.target.value)}
>
{items.map(item => (
<option key={item} value={item}>
{item}
</option>
))}
</select>


<h2>Selected: {selected}</h2>
</>
)
}


// Usage
<SelectExample
name="fruits"
items={['Select a fruit', 'Banana', 'Apple', 'Orange']}
/>