React JSX: sélectionner "sélectionné" sur l'option sélectionnée
Dans un composant React pour un menu <select>
, je dois définir l'attribut selected
sur l'option qui reflète l'état de l'application.
Dans render()
, le optionState
est passé du propriétaire de l'état au composant SortMenu. Les valeurs d'option sont transmises sous la forme props
à partir de 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
Cependant, cela déclenche une erreur de syntaxe sur la compilation JSX.
Cela élimine l'erreur de syntaxe mais ne résout évidemment pas le problème:
var selected = (optionState === option.value) ? 'selected' : 'false';
<option value={option.value} selected={selected}>{option.label}</option>
J'ai aussi essayé ceci:
var selected = (optionState === option.value) ? true : false;
<option value={option.value} {selected ? 'selected' : ''}>{option.label}</option>
Est y at-il un moyen recommandé de résoudre ce problème?
10 réponses
Réagir comprend automatiquement les booléens à cette fin, de sorte que vous pouvez simplement écrire (note: non recommandé)
<option value={option.value} selected={optionsState == option.value}>{option.label}</option>
Et il affichera' sélectionné ' de manière appropriée.
Cependant, React rend cela encore plus facile pour vous. Au lieu de définir selected
sur chaque option, vous pouvez (et devriez) simplement écrire value={optionsState}
sur la balise select elle-même :
<select value={optionsState}>
<option value="A">Apple</option>
<option value="B">Banana</option>
<option value="C">Cranberry</option>
</select>
Plus d'infos sur http://facebook.github.io/react/docs/forms.html#why-select-value.
Vous pouvez faire ce que React vous avertit lorsque vous essayez de définir la propriété" selected " du <option>
:
Utiliser le
defaultValue
ouvalue
accessoires sur<select>
au lieu deselected
sur<option>
.
Ainsi, vous pouvez utiliser options.value
sur defaultValue
de votre select
Voici une solution complète qui intègre la meilleure réponse et les commentaires ci-dessous (ce qui pourrait aider quelqu'un qui a du mal à tout rassembler):
Dans le composant principal:
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} onChange{this.handleChange} />
)
}
}
Composant inclus (qui est maintenant une fonctionnalité sans état):
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>
)
Le composant principal conserve la valeur sélectionnée pour fruit (dans l'état), le composant inclus affiche l'élément select et les mises à jour sont renvoyées au composant principal pour mettre à jour son état (qui revient ensuite en boucle au composant inclus pour modifier la valeur sélectionnée).
Notez l'utilisation d'un prop de nom qui vous permet de déclarer une seule méthode handleChange pour d'autres champs sur le même formulaire quel que soit leur type.
***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>);
}
});
J'ai eu un problème avec les balises <select>
Ne pas mettre à jour vers le bon <option>
lorsque l'état change. Mon problème semblait être que si vous effectuez un rendu deux fois de suite, la première fois sans <option>
présélectionné mais la deuxième fois avec un, alors la balise <select>
ne se met pas à jour sur le second rendu, mais reste sur la valeur par défaut en premier .
J'ai trouvé une solution à cela en utilisant refs . Vous devez obtenir une référence à votre nœud de balise <select>
(qui peut être imbriqué dans un composant), puis mettez à jour manuellement la propriété value
sur elle, dans le crochet componentDidUpdate
.
componentDidUpdate(){
let selectNode = React.findDOMNode(this.refs.selectingComponent.refs.selectTag);
selectNode.value = this.state.someValue;
}
Ajoutez Simplement comme première option de votre balise select:
<option disabled hidden value=''></option>
Cela deviendra par défaut et lorsque vous sélectionnez une option valide sera définie sur votre état
Poster une réponse similaire pour 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>
)
}
Voici le dernier exemple de la façon de le faire , à Partir de réagir docs
class FlavorForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: 'coconut'};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
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 La Croix 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>
);
}
}
J'ai une solution simple suit le HTML de base.
<input
type="select"
defaultValue=""
>
<option value="" disabled className="text-hide">Please select</option>
<option>value1</option>
<option>value1</option>
</input>
.text-hide
est la classe d'un bootstrap, si vous n'utilisez pas bootstrap, vous êtes ici:
.text-hide {
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
J'ai contourné un problème similaire en définissant defaultProps:
ComponentName.defaultProps = {
propName: ''
}
<select value="this.props.propName" ...
Alors maintenant j'évite les erreurs sur la compilation si mon accessoire n'existe pas avant le montage.