【问题标题】:Conditional form rendering in react反应中的条件表单渲染
【发布时间】:2020-01-20 08:01:03
【问题描述】:

因此,我正在尝试根据所选游戏类型有条件地呈现一个表单以开始新的飞镖游戏。该表单具有本地状态并“知道”选择了哪个游戏。因此,在选择游戏“X01”时,我需要一个变体,流动和外出下拉,而游戏“Cricket”只需要一个额外的变体下拉(其他值,而不是x01变体)。我开始设计一个游戏形式,如下所示:

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,我该怎么做?

提前感谢您的任何提示!

【问题讨论】:

  • 根据 this.state.game 你想在哪个选择框组件上显示?
  • x01 将具有三个选择框(x01variant、inCondition、outCondition),而 cricket 将只有一个(变体),而 split-score(即将到来)将有一个,并且全天候(即将到来将有一个)
  • 我建议将表单导出到各自的组件中,因为有很多游戏模式,您的组件肯定会变得非常混乱。

标签: javascript reactjs forms conditional-formatting


【解决方案1】:

当游戏模式设置为“板球”时,您可以有条件地渲染变体选择输入

{this.state.game === 'Cricket' && (
  <SelectInput />
)}

你可以这样写的原因是因为在 JavaScript 中 && 运算符基本上返回第一个值如果它是假的,如果第一个值是真的返回第二个值。 IE。 如果“a”为假,a && b 将返回“a”,如果“a”为真,它将返回“b”。 所以在这种情况下,当this.state.game === 'Cricket' 时,JSX 代码将被返回,从而呈现表单输入。

一个额外的提示! 如果你想根据条件渲染两个 JSX 元素之一,你可以使用三元表达式!

{this.state.game === 'Cricket' ? (
  // Renders when game mode is 'Cricket'
  <Cricket />
) : (
  // Renders when game mode is NOT 'Cricket'
  <SomeOtherGame />
)}

【讨论】:

  • 但是我还需要隐藏三个与 x01 相关的输入!并且还会有更多其他领域的游戏。
  • 然后也有条件地渲染它们!对于 x01 输入,您可以说 this.state.game === 'X01'
【解决方案2】:

所以在这种情况下,您需要一个通用且简单的解决方案,因此在您的状态下,由于您只有有限数量的游戏,您可以拥有如下所示的状态变量。

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 Assume 的密钥

现在你需要找到xo1游戏的字段

const findFields = (currentGameKey) => {
  let selectBoxKeys = selectBoxEnabled[Object.keys(selectBoxEnabled).find(key => key === currentGameKey)]
 this.setState(selectBoxKeys)
}

现在您知道要显示哪些字段,因为您使用的是相同的组件 SelectInput ,您可以做一个简单的 array.map 并从配置中渲染字段。

我希望这可以更好地理解问题

【讨论】:

    猜你喜欢
    • 2019-07-27
    • 2022-12-10
    • 2022-01-17
    • 2019-03-25
    • 2021-05-01
    • 2019-12-05
    • 1970-01-01
    • 2020-07-31
    相关资源
    最近更新 更多