Условное отображение формы в реакции - PullRequest
0 голосов
/ 20 января 2020

Итак, я пытаюсь создать форму для запуска новой игры в дартс в зависимости от выбранного типа игры. Форма имеет локальное состояние и «знает», какая игра выбрана. Поэтому при выборе игры «X01» мне нужен вариант, выпадающий в InCondition и OutCondition, в то время как для игры «Крикет» нужен только один дополнительный выпадающий список для варианта (другие значения, кроме вариантов 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?

Заранее благодарен за любую подсказку!

Ответы [ 2 ]

2 голосов
/ 20 января 2020

Вы можете просто условно визуализировать ввод выбора варианта, когда режим игры установлен в «Крикет»

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

Причина, по которой вы можете написать это так, заключается в том, что в JavaScript оператор && в основном возвращает первое значение, если оно ложно, и второе значение, если первое значение равно truthy. то есть a && b вернет 'a', если 'a' ложно, и вернет 'b', если 'a' верно. Таким образом, в этом случае, когда 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 />
)}
0 голосов
/ 20 января 2020

Так что в этом случае вам нужно общее c и простое решение, поэтому в вашем штате, поскольку у вас есть только ограниченное количество игр, вы можете иметь переменную состояния, как показано ниже.

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 ​​ game

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

Теперь вы знаете, какие поля следует отображать, поскольку вы используете один и тот же компонент SelectInput , вы можете сделать простой array.map и визуализировать поля из конфигурации.

Я надеюсь, что это даст лучшее понимание проблемы

...