web-dev-qa-db-fra.com

Ignorer les modifications lors de l'utilisation de Formik avec React

J'utilise le formulaire Formik avec React. Chaque fois que l'utilisateur soumet (handleSubmit), je mets une option pour annuler ou non la modification ou la conserver.

Dans mon rendu,

      <Formik
        initialValues={this.state.experiment}
        onSubmit={this.handleSubmit}
        component={formikProps => (
          <ExperimentForm {...formikProps} submitText="Save Changes" />
        )}
      />

handleSubmit ()

  handleSubmit(formdata: any, actions: any) {
    const data = processFormData(formdata);

    let changes = this.detectChanges(this.state.experiment, data);

    this.setState({ tempFormData: data });
    // changed field exists
    if (changes.length !== 0) {

      this.setState({ 
        isDialogOpen: true,
        changedFields: changes,
      });

    } else {
      actions.setSubmitting(false);
      this.setState({
        message: 'Nothing Changed',
      });
    }
  }

keepChanges () et discardChanges ()

  keepChanges () {

    const data = this.state.tempFormData
    makeMutation(UpdateExperimentQuery, {
      update: {
        id: this.props.match.params.id,
        data,
      },
    })
      .then(responseData => {
        console.log(responseData)
        this.setState({ isDialogOpen: false });

        this.props.history.Push('/i/experiments');

      })
      .catch(err => {

        this.setState({
          message: 'Error Updating Experiment',
        });
        console.log(err);
      });

  }

  discardChanges () {
      this.setState({ isDialogOpen: false });
      this.componentWillMount();
  }

La keepChanges() met à jour les données avec le champ donné, mais discardChanges ferme simplement la boîte de dialogue mais ne réinitialise pas les données à leur valeur d'origine même si j'essaie d'appeler componentWillMount() qui récupère et restitue les données d'origine inchangées dans la base de données.

Comment puis-je réinitialiser les champs lorsque je choisis d'annuler les modifications?

Modifier

  discardChanges () {
      this.formik.current.resetForm();
      this.setState({ isDialogOpen: false });
      this.componentWillMount();
  }

// J'obtiens une erreur lorsque je fais React.createRef ();

class EditExperiment extends Component<EditExperimentProps, EditState> {
  constructor(props: EditExperimentProps) {
    super(props);
    this.formik = React.createRef();

    this.state = {
      experiment: null,
      message: null,
      changedFields: [],
      isDialogOpen: false,
      tempFormData: []
    };

    this.handleSubmit = this.handleSubmit.bind(this);
    this.clearMessage = this.clearMessage.bind(this);
    this.detectChanges = this.detectChanges.bind(this);
    this.keepChanges = this.keepChanges.bind(this);
    this.discardChanges = this.discardChanges.bind(this);
  }

EDIT2

type EditExperimentProps = {
  history: RouterHistory,
  match: Match,
  experiments: ExperimentsState,
  refetch: () => void,
};
type EditState = {
  experiment: ?Experiment,
  message: ?string,
};

class EditExperiment extends Component<EditExperimentProps, EditState> {
  constructor(props: EditExperimentProps) {
    super(props);
    this.formik = React.createRef();

    this.state = {
      experiment: null,
      message: null,
      changedFields: [],
      isDialogOpen: false,
      tempFormData: []
    };

    this.handleSubmit = this.handleSubmit.bind(this);
    this.clearMessage = this.clearMessage.bind(this);
    this.detectChanges = this.detectChanges.bind(this);
    this.keepChanges = this.keepChanges.bind(this);
    this.discardChanges = this.discardChanges.bind(this);
  }
6
Dawn17

Pour réinitialiser le Formik, vous devez appeler resetForm - voir un exemple ici .

  handleSubmit(formdata: any, actions: any) {
    ...

    // changed field exists
    if (changes.length !== 0) {
      ...
    } else {
      actions.setSubmitting(false);
      actions.resetForm();
    }
  }

ÉDITER:

Il existe une autre façon d'obtenir des "actions" et de les appeler n'importe où dans le composant en utilisant react refs:

constructor(props) {
  super(props);
  this.formik = React.createRef();
}

//somewhere in render

<Formik
  ref={this.formik}
  initialValues={this.state.experiment}
  onSubmit={this.handleSubmit}
  component={formikProps => (
    <ExperimentForm {...formikProps} submitText="Save Changes" />
  )}
/>

// now somewhere else in the same component ...
componentDidUpdate(prevProps) {
  if(somethingHappend) {
    if(this.formik.current) {
      this.formik.current.resetForm();
    }
  }
}
5
Tomasz Mularczyk

Vous devez inclure l'état initial lorsque vous souhaitez utiliser resetForm. Exemple:

    this.formik.current.resetForm(this.initialState.experiment);

Cela signifie que vous devez également enregistrer l'état initial:

constructor(props) {
    super(props);
    this.initialState = this.state;
}
2
Diego Berolatti