反应中的条件表单渲染
Conditional form rendering in react
所以我正在尝试呈现一个表单,以根据所选的游戏类型有条件地开始新的飞镖游戏。该表单有一个本地状态和 "knows" 选择了哪个游戏。 So when selecting game "X01" I need a variant, inCondition and outCondition Dropdown whereas the game "Cricket" just needs one additional dropdown for variant (other values than x01 variants).我开始设计一个看起来像这样的游戏形式:
gameform.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import SelectInputMultiple from '../common/SelectInputMultiple';
import SelectInput from '../common/SelectInput';
import { games, x01Variants, conditions, cricketVariants } from './assets';
export default class GameForm extends Component {
constructor(props) {
super(props);
this.players = props;
this.handleMultipleChange = this.handleMultipleChange.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
state = {
selectedPlayers: [],
game: 'x01',
x01variant: '501',
inCondition: 'straight',
outCondition: 'double',
cricketVariant: 'cutthroat',
errors: {}
};
formIsValid() {
const _errors = {};
if (this.state.selectedPlayers.length === 0)
_errors.selectedPlayers = 'You need to select at least one player';
this.setState({
errors: _errors
});
return Object.keys(_errors).length === 0;
}
handleChange = e => {
this.setState({
[e.target.name]: e.target.value
});
};
handleMultipleChange = e => {
let _selectedPlayers = [...e.target.options]
.filter(o => o.selected)
.map(o => o.value);
this.setState(prevState => ({
selectedPlayers: { ...prevState.selectedPlayers, _selectedPlayers }
}));
};
handleSubmit = e => {
e.preventDefault();
if (!this.formIsValid()) return;
let _game = {
selectedPlayers: this.state.selectedPlayers,
game: this.state.game,
x01Variant: this.state.x01variant,
inCondition: this.state.inCondition,
outCondition: this.state.outCondition,
cricketVariant: this.state.cricketVariant
};
this.props.onSubmit(_game);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<SelectInputMultiple
id="players"
label="Players"
name="players"
onChange={this.handleMultipleChange}
options={this.props.players}
error={this.state.errors.selectedPlayers}
/>
<SelectInput
id="game"
label="Game Type"
name="game"
onChange={this.handleChange}
options={games}
value={this.state.game}
error={this.state.errors.game}
/>
<SelectInput
id="x01Variant"
label="X01 Variants"
name="x01Variant"
onChange={this.handleChange}
options={x01Variants}
value={this.state.x01variant}
error={this.state.errors.x01Variants}
/>
<SelectInput
id="inCondition"
label="In Condition"
name="inCondition"
onChange={this.handleChange}
options={conditions}
value={this.state.inCondition}
error={this.state.errors.condition}
/>
<SelectInput
id="outCondition"
label="Out Condition"
name="outCondition"
onChange={this.handleChange}
options={conditions}
value={this.state.outCondition}
error={this.state.errors.condition}
/>
<SelectInput
id="cricketVariant"
label="Variant"
name="cricketVariant"
onChange={this.handleChange}
options={cricketVariants}
value={this.state.cricketVariant}
error={this.state.errors.cricketVariant}
/>
<input type="submit" value="Start Game" className="btn btn-primary" />
</form>
);
}
}
GameForm.propTypes = {
onSubmit: PropTypes.func.isRequired,
players: PropTypes.array
};
所以我的目标是只显示与游戏类型相关联的相应字段。我该怎么做取决于 this.state.game
?
提前感谢任何提示!
当游戏模式设置为 "Cricket"
时,您可以有条件地渲染变体 select 输入
{this.state.game === 'Cricket' && (
<SelectInput />
)}
您可以这样写的原因是因为在 JavaScript 中,&& 运算符基本上 return 如果第一个值是假的,第二个值是如果第一个值是真的。 IE。
如果 'a' 为假,a && b 将 return 'a',如果 'a' 为真,它将 return 'b'。
所以在这种情况下,当 this.state.game === 'Cricket'
时,JSX 代码将被 return 编辑,从而呈现表单输入。
额外提示!
如果你想根据条件渲染两个 JSX 元素之一,你可以只使用三元表达式!
{this.state.game === 'Cricket' ? (
// Renders when game mode is 'Cricket'
<Cricket />
) : (
// Renders when game mode is NOT 'Cricket'
<SomeOtherGame />
)}
所以在这种情况下,您需要一个通用且简单的解决方案,因此在您的状态下,由于您只有有限数量的游戏,您可以拥有一个状态变量,如下所示。
state = {selectBoxEnabled : {xo1: ['xo1variant', 'inCondition', 'outCondition'], cricket: ['variant'], 'split-score': ['split-score_select']} }
所以上面的 selectBoxEnabled 字段与您的下拉字段具有相同的键
Game Select Box : xo1, cricket, split-score has option values
因此,当用户选择一个选项时,您将获得密钥 xo1
假设
现在你需要找到xo1游戏
的字段
const findFields = (currentGameKey) => {
let selectBoxKeys = selectBoxEnabled[Object.keys(selectBoxEnabled).find(key => key === currentGameKey)]
this.setState(selectBoxKeys)
}
现在您知道要显示哪些字段,因为您使用的是相同的组件 SelectInput
,您可以做一个简单的 array.map 并从配置中呈现字段。
我希望这能让你更好地理解这个问题
所以我正在尝试呈现一个表单,以根据所选的游戏类型有条件地开始新的飞镖游戏。该表单有一个本地状态和 "knows" 选择了哪个游戏。 So when selecting game "X01" I need a variant, inCondition and outCondition Dropdown whereas the game "Cricket" just needs one additional dropdown for variant (other values than x01 variants).我开始设计一个看起来像这样的游戏形式:
gameform.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import SelectInputMultiple from '../common/SelectInputMultiple';
import SelectInput from '../common/SelectInput';
import { games, x01Variants, conditions, cricketVariants } from './assets';
export default class GameForm extends Component {
constructor(props) {
super(props);
this.players = props;
this.handleMultipleChange = this.handleMultipleChange.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
state = {
selectedPlayers: [],
game: 'x01',
x01variant: '501',
inCondition: 'straight',
outCondition: 'double',
cricketVariant: 'cutthroat',
errors: {}
};
formIsValid() {
const _errors = {};
if (this.state.selectedPlayers.length === 0)
_errors.selectedPlayers = 'You need to select at least one player';
this.setState({
errors: _errors
});
return Object.keys(_errors).length === 0;
}
handleChange = e => {
this.setState({
[e.target.name]: e.target.value
});
};
handleMultipleChange = e => {
let _selectedPlayers = [...e.target.options]
.filter(o => o.selected)
.map(o => o.value);
this.setState(prevState => ({
selectedPlayers: { ...prevState.selectedPlayers, _selectedPlayers }
}));
};
handleSubmit = e => {
e.preventDefault();
if (!this.formIsValid()) return;
let _game = {
selectedPlayers: this.state.selectedPlayers,
game: this.state.game,
x01Variant: this.state.x01variant,
inCondition: this.state.inCondition,
outCondition: this.state.outCondition,
cricketVariant: this.state.cricketVariant
};
this.props.onSubmit(_game);
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<SelectInputMultiple
id="players"
label="Players"
name="players"
onChange={this.handleMultipleChange}
options={this.props.players}
error={this.state.errors.selectedPlayers}
/>
<SelectInput
id="game"
label="Game Type"
name="game"
onChange={this.handleChange}
options={games}
value={this.state.game}
error={this.state.errors.game}
/>
<SelectInput
id="x01Variant"
label="X01 Variants"
name="x01Variant"
onChange={this.handleChange}
options={x01Variants}
value={this.state.x01variant}
error={this.state.errors.x01Variants}
/>
<SelectInput
id="inCondition"
label="In Condition"
name="inCondition"
onChange={this.handleChange}
options={conditions}
value={this.state.inCondition}
error={this.state.errors.condition}
/>
<SelectInput
id="outCondition"
label="Out Condition"
name="outCondition"
onChange={this.handleChange}
options={conditions}
value={this.state.outCondition}
error={this.state.errors.condition}
/>
<SelectInput
id="cricketVariant"
label="Variant"
name="cricketVariant"
onChange={this.handleChange}
options={cricketVariants}
value={this.state.cricketVariant}
error={this.state.errors.cricketVariant}
/>
<input type="submit" value="Start Game" className="btn btn-primary" />
</form>
);
}
}
GameForm.propTypes = {
onSubmit: PropTypes.func.isRequired,
players: PropTypes.array
};
所以我的目标是只显示与游戏类型相关联的相应字段。我该怎么做取决于 this.state.game
?
提前感谢任何提示!
当游戏模式设置为 "Cricket"
时,您可以有条件地渲染变体 select 输入{this.state.game === 'Cricket' && (
<SelectInput />
)}
您可以这样写的原因是因为在 JavaScript 中,&& 运算符基本上 return 如果第一个值是假的,第二个值是如果第一个值是真的。 IE。
如果 'a' 为假,a && b 将 return 'a',如果 'a' 为真,它将 return 'b'。
所以在这种情况下,当 this.state.game === 'Cricket'
时,JSX 代码将被 return 编辑,从而呈现表单输入。
额外提示! 如果你想根据条件渲染两个 JSX 元素之一,你可以只使用三元表达式!
{this.state.game === 'Cricket' ? (
// Renders when game mode is 'Cricket'
<Cricket />
) : (
// Renders when game mode is NOT 'Cricket'
<SomeOtherGame />
)}
所以在这种情况下,您需要一个通用且简单的解决方案,因此在您的状态下,由于您只有有限数量的游戏,您可以拥有一个状态变量,如下所示。
state = {selectBoxEnabled : {xo1: ['xo1variant', 'inCondition', 'outCondition'], cricket: ['variant'], 'split-score': ['split-score_select']} }
所以上面的 selectBoxEnabled 字段与您的下拉字段具有相同的键
Game Select Box : xo1, cricket, split-score has option values
因此,当用户选择一个选项时,您将获得密钥 xo1
假设
现在你需要找到xo1游戏
的字段const findFields = (currentGameKey) => {
let selectBoxKeys = selectBoxEnabled[Object.keys(selectBoxEnabled).find(key => key === currentGameKey)]
this.setState(selectBoxKeys)
}
现在您知道要显示哪些字段,因为您使用的是相同的组件 SelectInput
,您可以做一个简单的 array.map 并从配置中呈现字段。
我希望这能让你更好地理解这个问题