ReactでFormik
フォームを使用しています。ユーザーが送信するたびに(handleSubmit)、変更を破棄するか、変更を保持するかを選択できます。
私のレンダリングでは、
_ <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()および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();
}
_
keepChanges()
は指定されたフィールドでデータを正常に更新しますが、discardChanges
はダイアログを閉じますが、componentWillMount()
を呼び出そうとしても、データを元の値にリセットしませんこれは、DB内の元の変更されていないデータをフェッチしてレンダリングします。
変更を破棄することを選択した場合、どのようにフィールドをリセットできますか?
編集
_ discardChanges () {
this.formik.current.resetForm();
this.setState({ isDialogOpen: false });
this.componentWillMount();
}
_
// 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);
}
_
編集2
_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);
}
_
Formikをリセットするには、 resetForm
を呼び出す必要があります-例 ここ を参照してください。
handleSubmit(formdata: any, actions: any) {
...
// changed field exists
if (changes.length !== 0) {
...
} else {
actions.setSubmitting(false);
actions.resetForm();
}
}
編集:
「アクション」を取得し、コンポーネントの任意の場所でreact ref
sを使用してそれらを呼び出す別の方法があります。
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();
}
}
}
ResetFormを使用する場合は、初期状態を含める必要があります。例:
this.formik.current.resetForm(this.initialState.experiment);
つまり、initialStateも保存する必要があります。
constructor(props) {
super(props);
this.initialState = this.state;
}