Реагировать - бесконечно l oop при изменении состояния с onChange - PullRequest
0 голосов
/ 28 марта 2020

У меня есть компонент с формой внутри. Поля формы зависят от состояния компонента, который обновляется в методах onChange. После нажатия кнопки отправки компонент отправляет поля формы родительскому компоненту, а затем обновляет хранилище. При вызове метода onChange возникает ошибка «Превышена максимальная глубина обновления. Это может произойти, когда компонент повторно вызывает setState внутри componentWillUpdate или componentDidUpdate. React ограничивает количество вложенных обновлений, чтобы предотвратить бесконечные циклы.»
Я не могу найти причина, по которой al oop возникает внутри компонента MemberForm.
Однако при отладке я понял, что при изменении состояния (не для функции onChange) также отображается родительский компонент AggiungiSocio. Однако состояние компонента «MemberForm» никоим образом не связано с компонентом «AggiungiSocio».
Что вызывает этот неожиданный рендеринг? Как мне избежать этого?

Странно то, что я также использую компонент "MemberForm" в компоненте "ModificaSocio", где я передаю поля формы в качестве свойств. В этом компоненте "ModificaSocio" все работает правильно.

Подводя итог
AddSocio -> MemberForm не работает
EditSocio -> MemberForm работает

AggiungiSocio

import React, { Component, Fragment } from "react";
import {
  Row,
  Card,
  CardBody,
  CardTitle,
  CardSubtitle,
} from "reactstrap";
import IntlMessages from "../../../helpers/IntlMessages";
import { Colxx } from "../../../components/common/CustomBootstrap";
import MemberForm from "../../../containers/form/MemberForm";
import {injectIntl} from "react-intl";
import {connect} from "react-redux";
import {addMemberDetail} from "../../../redux/memberDetail/actions";
import {Socio} from "../../../models/socio";

class AggiungiSocio extends Component {
  constructor(props) {
    super(props);
  }

  aggiungiSocio = (socio) => {
    console.log(socio);
    this.props.addMemberDetail(socio);
  };

  render() {
    console.log("render aggiungi socio");
    const {
      loading
    } = this.props.memberDetail;
    return (
      <Fragment>
        <Row className="mb-4">
          <Colxx xxs="12">
            <Card>
              <CardBody>
                <CardTitle>
                  <IntlMessages id="pages.member.add-member"/>
                </CardTitle>
                <CardSubtitle>
                  <IntlMessages id="pages.member.add-member-description"/>
                </CardSubtitle>
                {loading ? (
                  <MemberForm onSubmit={this.aggiungiSocio}/>
                ) : (
                  <div className="loading"/>
                )
                }
              </CardBody>
            </Card>
          </Colxx>
        </Row>
      </Fragment>
    )
  }
}

const mapStateToProps = ({memberDetail}) => {
  return {
    memberDetail
  };
};
export default injectIntl(
  connect(
    mapStateToProps,
    {
      addMemberDetail
    }
  )(AggiungiSocio)
);

ModificaSocio

import React, { Component, Fragment } from "react";
import {
  Row,
  Card,
  CardBody,
  CardTitle
} from "reactstrap";
import IntlMessages from "../../../helpers/IntlMessages";
import { Colxx } from "../../../components/common/CustomBootstrap";
import "react-datepicker/dist/react-datepicker.css";
import MemberForm from "../../../containers/form/MemberForm";
import {injectIntl} from "react-intl";
import {connect} from "react-redux";
import {getMemberDetail, editMemberDetail} from "../../../redux/memberDetail/actions";

class ModificaSocio extends Component {
  constructor(props) {
    super(props);
    this.state = {
    };
  }
  modificaSocio = (socio) => {
    this.props.editMemberDetail(socio);
  }
  render() {
    const {
      member,
      loading
    } = this.props.memberDetail;
    return (
      <Fragment>
        <Row className="mb-4">
          <Colxx xxs="12">
            <Card>
              <CardBody>
                <CardTitle>
                  <IntlMessages id="pages.member.edit-member"/>
                </CardTitle>
                {loading ? (
                  <MemberForm member={member} onSubmit={this.modificaSocio}/>
                ): (
                  <div className="loading" />
                )
                }
              </CardBody>
            </Card>
          </Colxx>
        </Row>
      </Fragment>
    )
  }
}

const mapStateToProps = ({memberDetail}) => {
  return {
    memberDetail
  };
};
export default injectIntl(
  connect(
    mapStateToProps,
    {
      editMemberDetail,
      getMemberDetail
    }
  )(ModificaSocio)
);

MemberForm

import React, { Component } from "react";
import {
  Input,
  FormGroup,
  Label,
  Button,
  Form
} from "reactstrap";
import IntlMessages from "../../helpers/IntlMessages";
import DatePicker from "react-datepicker";
import "react-tagsinput/react-tagsinput.css";
import "react-datepicker/dist/react-datepicker.css";
import "rc-switch/assets/index.css";
import "rc-slider/assets/index.css";
import "react-rater/lib/react-rater.css";
import { Colxx } from "../../components/common/CustomBootstrap";
import Select from "react-select";
import CustomSelectInput from "../../components/common/CustomSelectInput";
import moment from "moment";
import {Socio} from "../../models/socio";

class MemberForm extends Component {
  constructor(props) {
    super(props);
    moment.locale("it");
    this.state = {
      member: (typeof this.props.member === 'undefined') ? Socio : this.props.member,
      selectQualifica: [{
        label: (typeof this.props.member === 'undefined') ? '' : this.props.member.qualifica,
        value: (typeof this.props.member === 'undefined') ? '' : this.props.member.qualifica
      }],
      selectTitolo: [{
        label: (typeof this.props.member === 'undefined') ? '' : this.props.member.titolo,
        value: (typeof this.props.member === 'undefined') ? '' : this.props.member.titolo
      }],
      dataDiNascita: moment((typeof this.props.member === 'undefined') ? null : this.props.member.dataDiNascita, "DD/MM/YYYY"),
      dataRichiestaIscrizione: moment((typeof this.props.member === 'undefined') ? null : this.props.member.dataRichiestaIscrizione, "DD/MM/YYYY"),
      dataAccettazione: moment((typeof this.props.member === 'undefined') ? null : this.props.member.dataAccettazione, "DD/MM/YYYY")
    }
  }

  handleChangeQualifica = qualifica => {
    this.setState({
      member: {
        ...this.state.member,
        qualifica: qualifica.value
      },
      selectQualifica: [{
        label: qualifica.value,
        value: qualifica.value
      }]
    });
  }
  handleChangeTitolo = titolo => {
    this.setState({
      member: {
        ...this.state.member,
        titolo: titolo.value
      },
      selectTitolo: [{
        label: titolo.value,
        value: titolo.value
      }]
    });
  }
  handlerChange = event => {
    const name = event.target.name;
    const value = event.target.value;
    if (value!=this.state.member[name]) {
      console.log("il valore è cambiato, aggiorno stato");
      console.log(value, this.state.member[name]);
      this.setState({
        member: {
          ...this.state.member,
          [name]: value
        }
      });
    } else {
      console.log("il valore è lo stesso!, non aggiorno stato");
      console.log(value, this.state.member[name]);
    }
  }
  handleChangeDataNascita = date => {
    this.setState({
      member: {
        ...this.state.member,
        dataDiNascita: date.format("DD/MM/YYYY")
      },
      dataDiNascita: date
    });
  };
  handleChangeDataRichiestaIscrizione = date => {
    this.setState({
      member: {
        ...this.state.member,
        dataRichiestaIscrizione: date.format("DD/MM/YYYY")
      },
      dataRichiestaIscrizione: date
    });
  };
  handleChangeDataAccettazione = date => {
    this.setState({
      member: {
        ...this.state.member,
        dataAccettazione: date.format("DD/MM/YYYY")
      },
      dataAccettazione: date
    });
  };
  handleSubmit = () => {
    this.props.onSubmit(this.state.member);
  }

  render () {
    console.log("render memberform");
    const {
      member,
      selectQualifica,
      selectTitolo,
      dataDiNascita,
      dataRichiestaIscrizione,
      dataAccettazione
    } = this.state;
    return (
      (member &&
        <Form>
          <FormGroup row>
            <Colxx sm={2}>
              <FormGroup>
                <Label for="memberTitle">
                  <IntlMessages id="member.idSocio"/>
                </Label>
                <Input
                  disabled
                  readOnly
                  type="text"
                  name="memberId"
                  id="memberId"
                  defaultValue={member.numeroSocio}
                />
              </FormGroup>
            </Colxx>
            <Colxx sm={2}>
              <FormGroup>
                <Label for="memberTitle">
                  <IntlMessages id="member.title"/>
                </Label>
                <Select
                  components={{Input: CustomSelectInput}}
                  className="react-select"
                  classNamePrefix="react-select"
                  name="form-field-name"
                  id="memberTitle"
                  options={[
                    {label: "Sig", value: "Sig", key: 0},
                    {label: "Sig.ra", value: "Sig.ra", key: 1}
                  ]}
                  value={selectTitolo}
                  onChange={this.handleChangeTitolo.bind(this)}
                />
              </FormGroup>
            </Colxx>
            <Colxx sm={3}>
              <Label for="memberName">
                <IntlMessages id="member.name"/>
              </Label>
              <Input
                type="text"
                name="nome"
                id="memberName"
                value={member.nome}
                onChange={this.handlerChange.bind(this)}
              />
            </Colxx>
            <Colxx sm={3}>
              <Label for="memberSurname">
                <IntlMessages id="member.surname"/>
              </Label>
              <Input
                type="text"
                name="cognome"
                id="memberSurname"
                value={member.cognome}
                onChange={this.handlerChange.bind(this)}
              />
            </Colxx>
            <Colxx sm={2}>
              <Label for="memberSurname">
                <IntlMessages id="member.birthday"/>
              </Label>
              <DatePicker
                dateFormat="DD/MM/YYYY"
                selected={dataDiNascita}
                onChange={this.handleChangeDataNascita.bind(this)}
                id="memberBirthday"/>
            </Colxx>
          </FormGroup>

          <FormGroup row>
            <Colxx sm={3}>
              <FormGroup>
                <Label for="birth-comune">
                  <IntlMessages id="member.birth-comune"/>
                </Label>
                <Input
                  type="text"
                  name="comuneDiNascita"
                  id="birth-comune"
                  onChange={this.handlerChange.bind(this)}
                  value={member.comuneDiNascita}
                />
              </FormGroup>
            </Colxx>
            <Colxx sm={2}>
              <FormGroup>
                <Label for="birth-provincia">
                  <IntlMessages id="member.birth-provincia"/>
                </Label>
                <Input
                  type="text"
                  name="provinciaDiNascita"
                  id="birth-provincia"
                  onChange={this.handlerChange.bind(this)}
                  value={member.provinciaDiNascita}
                />
              </FormGroup>
            </Colxx>
            <Colxx sm={4}>
              <FormGroup>
                <Label for="residential-address">
                  <IntlMessages id="member.residential-address"/>
                </Label>
                <Input
                  type="text"
                  name="indirizzoDiResidenza"
                  id="residential-address"
                  onChange={this.handlerChange.bind(this)}
                  value={member.indirizzoDiResidenza}
                />
              </FormGroup>
            </Colxx>
            <Colxx sm={3}>
              <FormGroup>
                <Label for="codice-fiscale">
                  <IntlMessages id="member.codice-fiscale"/>
                </Label>
                <Input
                  type="text"
                  name="codiceFiscale"
                  id="codice-fiscale"
                  onChange={this.handlerChange.bind(this)}
                  value={member.codiceFiscale}
                />
              </FormGroup>
            </Colxx>
          </FormGroup>

          <FormGroup row>
            <Colxx sm={3}>
              <FormGroup>
                <Label for="data-richiesta-iscrizione">
                  <IntlMessages id="member.data-richiesta-iscrizione"/>
                </Label>
                <DatePicker
                  dateFormat="DD/MM/YYYY"
                  selected={dataRichiestaIscrizione}
                  onChange={this.handleChangeDataRichiestaIscrizione.bind(this)}
                  id="data-richiesta-iscrizione"/>
              </FormGroup>
            </Colxx>
            <Colxx sm={3}>
              <FormGroup>
                <Label for="data-accettazione">
                  <IntlMessages id="member.data-accettazione"/>
                </Label>
                <DatePicker
                  dateFormat="DD/MM/YYYY"
                  selected={dataAccettazione}
                  onChange={this.handleChangeDataAccettazione.bind(this)}
                  id="data-accettazione"/>
              </FormGroup>
            </Colxx>
            <Colxx sm={3}>
              <FormGroup>
                <Label for="payment">
                  <IntlMessages id="member.payment"/>
                </Label>
                <Input
                  type="text"
                  name="quotaVersata"
                  id="payment"
                  onChange={this.handlerChange.bind(this)}
                  value={member.quotaVersata}
                />
              </FormGroup>
            </Colxx>
            <Colxx sm={3}>
              <FormGroup>
                <Label for="qualification">
                  <IntlMessages id="member.qualification"/>
                </Label>
                <Select
                  components={{Input: CustomSelectInput}}
                  className="react-select"
                  classNamePrefix="react-select"
                  name="form-field-name"
                  id="qualification"
                  options={[
                    {label: "Socio", value: "Socio", key: 0},
                    {label: "Socio Fondatore", value: "Socio Fondatore", key: 1},
                    {label: "Consigliere", value: "Consigliere", key: 2}
                  ]}
                  value={selectQualifica}
                  onChange={this.handleChangeQualifica}
                />
              </FormGroup>
            </Colxx>
          </FormGroup>

          <Button color="primary" onClick={this.handleSubmit.bind(this)}>
            <IntlMessages id="pages.member.save"/>
          </Button>
        </Form>
      )
    )
  }
}
export default React.memo(MemberForm);

1 Ответ

0 голосов
/ 28 марта 2020

Вы не можете передавать параметры в функцию вне функции.

Правильно:

< ... onChange={function} />

Не правильно:

< ... onChange={function(params)} />

Для использования параметров вам нужно для вложения вашей функции в анонимную функцию:

< ... onChange={() => function(params)} />

В вашем случае вы хотите написать это:

< ... onChange={() => this.handlerChange.bind(this)} />
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...