在<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>
有没有推荐的解决方法?
React 让你更容易做到这一点。您可以(并且应该)简单地在 select 标签本身上写入value={optionsState}
,而不是在每个选项上定义selected
:
<select value={optionsState}>
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>
有关更多信息,请参阅 React 选择标签文档。
此外,React 会自动理解布尔值,因此您可以简单地编写(注意:不推荐)
<option value={option.value} selected={optionsState == option.value}>{option.label}</option>
它将适当地输出"已选择"。
当你尝试设置<option>
的"selected"属性时,你可以按照 React 警告你的方式做:
在
<select>
上使用defaultValue
或value
道具,而不是在<option>
上设置selected
。
因此,您可以在您选择的defaultValue
上使用options.value
这是一个完整的解决方案,其中包含最佳答案及其下方的评论(这可能有助于努力将其拼凑在一起的人):
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 元素,并将更新传递回主组件以更新其状态(然后循环回包含的组件以更改所选值)。
请注意,使用 name prop,它允许您为同一表单上的其他字段声明单个 handleChange 方法,而不管它们的类型如何。
我正在为语言选择器制作一个下拉菜单 - 但我需要下拉菜单在页面加载时显示当前语言。 我要么从 URL 参数example.com?user_language=fr
获取我的初始语言,要么从用户的浏览器设置中检测它。然后,当用户与下拉列表交互时,所选语言将更新,语言选择器下拉列表将显示当前所选语言。
由于整个线程一直在给出水果示例,因此我为您提供了各种水果美食。
-
首先,用一个基本的 React 功能组件回答最初提出的问题 - 两个有和没有 props 的例子,然后如何将组件导入到其他地方。
-
接下来,同样的例子 - 但用打字稿榨汁。
-
然后是一个额外的结局 - 使用Typescript的语言选择器下拉组件。
Basic 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 接受 props,也许你有一个输出字符串的函数,你可以使用fruitDetector
prop 传递它
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
使用打字稿
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 的宝贵资源
这是如何做到这一点的最新示例。来自 react 文档,以及自动绑定的"fat-arrow"方法语法。
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>
);
}
}
要点 - 受控组件
您希望设置"受控组件"。这将要求您在元素上设置值,并处理 on change 事件以更新值。
https://reactjs.org/docs/forms.html#controlled-components
例子
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']}
/>
使用 React 16.8。我们可以使用钩子来做到这一点,如以下示例所示
代码沙盒链接
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>
);
}
只需添加为选择标签的第一个选项:
<option disabled hidden value=''></option>
这将成为默认值,当您选择有效选项时,将在您的州设置一个有效选项
***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>);
}
});
使用defaultValue
预先选择"选择"的值。
<Select defaultValue={[{ value: category.published, label: 'Publish' }]} options={statusOptions} onChange={handleStatusChange} />
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>
);
}
}
我在状态更改时<select>
标签未更新到正确的<option>
时遇到了问题。我的问题似乎是,如果您快速连续渲染两次,第一次没有预先选择<option>
但第二次有一个,那么<select>
标签不会在第二次渲染时更新,而是保持默认的第一个。
我使用 refs 找到了解决这个问题的方法。您需要获取对<select>
标记节点(可能嵌套在某个组件中)的引用,然后在componentDidUpdate
挂钩中手动更新其上的value
属性。
componentDidUpdate(){
let selectNode = React.findDOMNode(this.refs.selectingComponent.refs.selectTag);
selectNode.value = this.state.someValue;
}
为 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>
)
}
<</div> div class="one_answers">我有一个简单的解决方案是遵循HTML基础知识。
<input
type="select"
defaultValue=""
>
<option value="" disabled className="text-hide">Please select</option>
<option>value1</option>
<option>value1</option>
</input>
.text-hide
是引导程序的类,如果您不使用引导程序,这里是:
.text-hide {
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
如果你使用Stateless,那么
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>
)
}
将选定内容添加到选项
设置输入值的一种非常常见的方法是将选定的属性添加到其元素之一。例如:
const Select = ({ values, callback, selected }) => {
return (
<select
disabled={disabled}
readOnly={readonly}
onChange={({ target: { value } }) => callback(value)}>
{values.map(([value, text]) => (
<option selected={selected === value} value={value}>
{text}
</option>
))}
</select>
);
}
设置选择的值
虽然这种方法与 HTML 非常相似并且感觉很直观,但有一种更简单的方法可以做同样的事情。React 为我们提供了一个共享 API,介于 、 和 之间,我们可以在其中使用 value 或 defaultValue(取决于输入是否受控)来设置字段的值。
使用此 API,我们最大限度地减少了检查所选值的工作量,并使代码更易于阅读和根据需要更新。下面是一个示例:
const Select = ({ values, callback, selected }) => {
return (
<select
disabled={disabled}
readOnly={readonly}
defaultValue={selected}
onChange={({ target: { value } }) => callback(value)}>
{values.map(([value, text]) => (
<option value={value}>
{text}
</option>
))}
</select>
);
}
请注意,上面的实现使用 defaultValue,因此它意味着组件不受控制。您可以通过使用 value 而不是 defaultValue 将此 Select 组件转换为受控组件。
有关组件的更详细说明以及使用示例,您可以查看 Select 组件。
参考:选定选项
我通过设置 defaultProps 解决了类似的问题:
ComponentName.defaultProps = {
propName: ''
}
<select value="this.props.propName" ...
所以现在如果我的道具在挂载之前不存在,我会避免编译错误。