在<select>菜单的React组件中,我需要在反映应用程序状态的选项上设置所选属性。
在render()中,optionState从状态所有者传递给SortMenu组件。选项值作为道具从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>
有没有解决这个问题的推荐方法?
下面是一个完整的解决方案,包含了最佳答案和下面的评论(这可能会帮助那些挣扎着把它们拼凑在一起的人):
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方法,而不管它们的类型是什么。
主点控制组件
您希望设置一个“受控组件”。这将要求您在元素上设置值,并处理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。我们可以像下面的例子一样使用钩子来实现这一点
Codesandbox链接
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>
);
}