反应中的条件表单渲染

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 并从配置中呈现字段。

我希望这能让你更好地理解这个问题