Невозможно выбрать элемент из поля выбора / написать в поле ввода.Я неправильно обрабатываю «ключ»? - PullRequest
0 голосов
/ 13 марта 2019

Я писал компонент с приведенным ниже кодом, который после рендеринга выглядит так:

enter image description here

Я использовал компоненты antd для визуализации полей. Проблема, с которой я сталкиваюсь, заключается в том, что я не могу ни выбрать из поля выбора, ни написать в поле ввода, как показано ниже. У меня такое ощущение, что я использую React key неуместно для mocFields в методе рендеринга, полученном из getMOCField.

import React, { Component } from "react";
import { Button, Icon, Select, Form, Input } from "antd";
const FormItem = Form.Item;
const Option = Select.Option;
import { FormComponentProps } from "antd/lib/form/Form";

type state = {
  mocFields: JSX.Element[]
};

export class MOC extends Component<FormComponentProps, state> {
  constructor(props) {
    super(props);
    this.state = {
      mocFields: []
    };
    this.addMOCField = this.addMOCField.bind(this);
    this.removeMOCField = this.removeMOCField.bind(this);
  }

  componentDidMount() {}

  componentWillReceiveProps(nextProps) {}

  removeMOCField(key, event: React.MouseEvent<HTMLElement>) {
    event.preventDefault();
    const { mocFields } = this.state;

    mocFields.splice(key, 1);

    this.setState({
      mocFields
    });
  }

  getMOCFieldFooter() {
    return (
      <div className="d-flex justify-content-between small">
        <div className="inline-block">
          <Button
            type="primary"
            shape="circle"
            icon="plus"
            ghost
            size="small"
            className="d-font mr-1"
            onClick={this.addMOCField}
          />
          <div
            className="text-primary pointer d-font inline-block letter-spacing-1"
            onClick={this.addMOCField}
          >
            Add another&nbsp;
          </div>
          <div className="d-font inline-block letter-spacing-1">or&nbsp;</div>
          <div className="text-primary pointer d-font inline-block letter-spacing-1">
            Create a new MOC
          </div>
        </div>
      </div>
    );
  }

  getMOCField(key) {
    const { getFieldDecorator } = this.props.form;

    return (
      <div className="d-flex justify-content-between">
        <div className="inline-block">
          <FormItem label="Select MOC">
            {getFieldDecorator(`selected_moc[${key}]`, {
              rules: [
                {
                  required: true,
                  message: "Please select moc"
                }
              ]
            })(
              <Select>
                <Option value={"A"}>A</Option>
                <Option value={"B"}>B</Option>
              </Select>
            )}
          </FormItem>
        </div>

        <div className="inline-block">
          <FormItem label="Recovery (%)">
            {getFieldDecorator(`recovery_percentage[${key}]`, {
              rules: [
                {
                  required: true,
                  message: "Please input the recovery percentage"
                }
              ]
            })(<Input type="number" step="0.000001" />)}
          </FormItem>
        </div>
        <div className="inline-block pointer">
          <span>
            <Icon type="close" onClick={this.removeMOCField.bind(this, key)} />
          </span>
        </div>
      </div>
    );
  }

  addMOCField(event: React.MouseEvent<HTMLElement>) {
    event.preventDefault();
    const { mocFields } = this.state;
    const MOCField = this.getMOCField(mocFields.length);
    mocFields.push(MOCField);

    this.setState({
      mocFields
    });
  }

  getAddMOCButton() {
    return (
      <div className="d-flex w-100 mt-3">
        <Button
          type="primary"
          ghost
          className="w-100"
          onClick={this.addMOCField}
        >
          <Icon type="plus-circle" />
          Add MOC
        </Button>
      </div>
    );
  }

  render() {
    const { mocFields } = this.state;
    const mocButton = this.getAddMOCButton();
    const toRender =
      mocFields.length > 0 ? (
        <div className="w-100 p-2 gray-background br-25">
          {mocFields.map((f, index) => (
            <div key={index}>{f}</div>
          ))}
          {this.getMOCFieldFooter()}
        </div>
      ) : (
        mocButton
      );

    return toRender;
  }
}

В чем может быть причина этого? Что я делаю неправильно? В настоящее время вышеуказанный компонент отображается следующим образом:

  • Если число полей в mocFields равно нулю, отображается кнопка для добавления новых полей.
  • После нажатия кнопки, mocField заполняется полем выбора и полем ввода, как показано выше. Ключ div определяется во время метода рендеринга.

1 Ответ

1 голос
/ 13 марта 2019

Кажется, что слушатели не работают, как только они сохранены в массиве. Я попытался встроить вызов getMOCField в функцию render, и это работает. Вот что я изменил, чтобы заставить его работать:

class MOC extends Component {
  // ...

  addMOCField(event) {
    event.preventDefault();

    const { mocFields } = this.state;

    // We only keep inside the state an array of number
    // each one of them represent a section of fields.
    const lastFieldId = mocFields[mocFields.length - 1] || 0;
    const nextFieldId = lastFieldId + 1;

    this.setState({
      mocFields: mocFields.concat(nextFieldId),
    });
  }

  removeMOCField(key, event) {
    event.preventDefault();

    this.setState(prevState => ({
      mocFields: prevState.mocFields.filter(field => field !== key)
    }));
  }

  render() {
    const { mocFields } = this.state;
    const mocButton = this.getAddMOCButton();
    const toRender =
      mocFields.length > 0 ? (
        <div className="w-100 p-2 gray-background br-25">
          {/* {mocFields.map((f, index) => (
                <div key={index}>{f}</div>
              ))} */}
          {mocFields.map(fieldIndex => (
            <div key={fieldIndex}>{this.getMOCField(fieldIndex)}</div>
          ))}
          {this.getMOCFieldFooter()}
        </div>
      ) : (
        mocButton
      );

    return toRender;
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...