0

I create registration/login/forgot-password forms using redux-form. Also I use react-intl for multilingual support. Changing language causes rerender of components and resets the forms.

I would like to reset form only when location is changed, but my solution seems to me not perfect

1) if I use destroyOnUnmount: true the case is next: when user started to fill e.g. registration form and then decided to change language -> form destroys on unmount and all fields are reset. 2) if destroyOnUnmount: false everything is OK, on language change form data doesn't destroy. But if to change route and then open again registration form - previous data is still present.

initialValues are not set

So I decided to set destroyOnUnmount: false

Then in App component I call action if location changes

  // reset redux forms on route change
  componentDidUpdate(prevProps) {
    if (this.props.location !== prevProps.location) {
      this.props.resetFormsAction();
    }
  }

and then in saga listen to action

export function* resetForms() {
  try {
    const forms = yield select(getForms);
    yield all(Object.keys(forms).map(form => put(reset(form))));
  } catch (e) {
    console.error(e);
  }
}

const commonSagas = [
  takeEvery(RESET_FORMS, resetForms),
];

export default commonSagas;

selector

export const getForms = (state: AppStore) => state.form;

This solution works fine, but is there any other implementation to reset/destroy form only when location is changed but not when change language is clicked

I have found similar question but it didn't help me

2 Answers2

0

You can reset form in saga instead of calling own action in componentDidUpdate()

  1. Set destroyOnUnmount: false
  2. Instead of reset you can use 'destroy' action from redux-forms
yield takeEvery('@@router/LOCATION_CHANGE', function* () {
      try {
        const forms = yield select(getForms);
        yield all(Object.keys(forms).map(form => put(destroy(form))));
      } catch (e) {
        console.error(e);
      }
    }
Igor S
  • 951
  • 7
  • 19
  • Thank you for quick answer! Yes, I have tried to use ```сonnected-react-router``` and to listen ```LOCATION_CHANGE``` for reset or destroy, but I see action LOCATION_CHANGE in redux dev tools also when I change language :( – Natallia Dubrouskaya Apr 05 '19 at 15:03
  • Get new location from saga payload and compare with location from state, if not equal than call destroy – Igor S Apr 05 '19 at 15:08
  • I checked: selector ```getLocation``` from ```сonnected-react-router``` returns the same `location` as action.payload.location. The same result if I create my own selector for location pathname `const getLocationPathname = (state: AppStore) => state.router.location.pathname;`. Hmmm... I'll try smth else. But thanks for advice! – Natallia Dubrouskaya Apr 05 '19 at 15:48
  • You can use 'select' effect to get actual location in saga and then check payload.location === yield select(state =} state.router.location) – Igor S Apr 05 '19 at 16:51
0

As a result, I decided to handle destroy in componentWillUnmount and saga.

Example

componentWillUnmount() {
    const { destroyFormRequestAction } = this.props;
    destroyFormRequestAction(FormTypes.registration, REGISTRATION_URL);
  }

and then listen action in my saga and check if route changed

...
export function* destroyForm(action: DestroyFormAction) {
  try {
    const routerLocation = yield select(getLocation);
    if (routerLocation.pathname !== action.payload.currentPath) {
      yield put(destroy(action.payload.formType));
    }
  } catch (e) {
    console.error(e); // tslint:disable-line
  }
}

const formSagas = [
  takeEvery(DESTROY_FORM_REQUEST, destroyForm),
];