0
votes

I'm using formik and yup in react native for a simple login screen. I got 2 forms sign in and signup, one or the other is rendered according to a redux state.

The problem starts when I switch between forms (without touching the form) the initial values does not change. Ex. I'm in LoginForm and then switch to RegisterForm, register form keep { email: '', password: '' } and values from loginform, this is wrong register form should get { firstName: '', surName: '', registerEmail: '', registerPassword: '', acceptTOC: false } .

LoginForm Props

LoginForm state

RegisterForm Props after switch

enter image description here I'm rendering form like this

<View style={styles.section}>
              {this.props.session.loginForm ? loginFormFormik() : registerForm()}
            </View>

Login Form

const loginFormFormik = () => {
      return (
        <Formik
          enableReinitialize={true}
          initialValues={{ email: '', password: '' }}
          onSubmit={this.onLogInPress}
          validationSchema={this.validationSchemaLogin}>
          {(formikProps) => {
            console.log('TCL: loginFormFormik -> formikProps', formikProps);
            const { handleSubmit } = formikProps;

            return (
              <View>
                <View style={[styles.section, styles.sectionStart, styles.loginForm]}>
                  <InputFormik
                    formikKey="email"
                    formikProps={formikProps}
                    placeholder="Type your account number or email"
                    label="Username"
                    keyboardType="email-address"
                    autoCapitalize="none"
                    autoCorrect={false}
                    returnKeyType="next"
                    onSubmitEditing={() => {
                      this.loginFormPasswordRef.focus();
                    }}
                  />
                  <InputFormik
                    formikKey="password"
                    formikProps={formikProps}
                    ref={(child) => {
                      if (child) {
                        this.loginFormPasswordRef = child.refProp;
                      }
                    }}
                    placeholder="Type your password"
                    label="Password"
                    secureTextEntry={this.state.showPassword}
                    returnKeyType="go"
                    containerStyle={inputContainer}
                    rightIcon={toggleViewIcon}
                  />
                  <ServerError message={this.props.session.loginError} />
                  <TouchableHighlight
                    onPress={() => this.props.navigation.navigate('ResetPassword')}
                    underlayColor={'transparent'}
                    style={styles.forgotPasswordLinkWrapper}>
                    <Text style={styles.forgotPasswordLink}>Forgot Password</Text>
                  </TouchableHighlight>
                </View>
                <View style={[styles.section, styles.sectionEnd]}>
                  <SubmitButton handleSubmit={handleSubmit} />
                  {formSwitchLink()}
                </View>
              </View>
            );
          }}
        </Formik>
      );
    };

Register Form

const registerForm = () => {
      return (
        <Formik
          enableReinitialize={true}
          initialValues={{
            firstName: '',
            surName: '',
            registerEmail: '',
            registerPassword: '',
            acceptTOC: false
          }}
          onSubmit={this.onRegisterPress}
          validationSchema={this.validationSchemaRegister}>
          {(formikProps) => {
            console.log('TCL: registerForm -> formikProps', formikProps);
            const { handleSubmit } = formikProps;
            return (
              <View>
                <View style={[styles.section, styles.sectionStart]}>
                  <InputFormik
                    formikKey="firstName"
                    formikProps={formikProps}
                    placeholder="Type your first name"
                    label="First name"
                    keyboardType="default"
                    autoCapitalize="words"
                    autoCorrect={false}
                    returnKeyType="next"
                    onSubmitEditing={() => {
                      this.registerFormSurNameRef.focus();
                    }}
                  />

                  <InputFormik
                    formikKey="surName"
                    formikProps={formikProps}
                    ref={(child) => {
                      if (child) {
                        this.registerFormSurNameRef = child.refProp;
                      }
                    }}
                    placeholder="Type your surname"
                    label="Surname"
                    keyboardType="default"
                    autoCapitalize="words"
                    autoCorrect={false}
                    returnKeyType="next"
                    onSubmitEditing={() => {
                      this.registerFormEmailRef.focus();
                    }}
                  />
                  <InputFormik
                    formikKey="registerEmail"
                    formikProps={formikProps}
                    ref={(child) => {
                      if (child) {
                        this.registerFormEmailRef = child.refProp;
                      }
                    }}
                    placeholder="Type your e-mail address"
                    label="E-mail"
                    keyboardType="email-address"
                    autoCapitalize="none"
                    autoCorrect={false}
                    returnKeyType="next"
                    onSubmitEditing={() => {
                      this.registerFormPasswordRef.focus();
                    }}
                  />
                  <InputFormik
                    formikKey="registerPassword"
                    formikProps={formikProps}
                    ref={(child) => {
                      if (child) {
                        this.registerFormPasswordRef = child.refProp;
                      }
                    }}
                    placeholder="Type your new password"
                    label="Password"
                    secureTextEntry={this.state.showPassword}
                    returnKeyType="go"
                    rightIcon={toggleViewIcon}
                    pwdStrength={true}
                  />
                  <SwitchFormik
                    label={'Accept Terms & Conditions to use this service.'}
                    accessibilityLabel="Please accept these terms and conditions"
                    formikKey="acceptTOC"
                    formikProps={formikProps}
                    errorStyle={errorText}
                  />
                </View>
                <ServerError message={this.props.session.registrationError} />
                <View style={[styles.section, styles.sectionEnd]}>
                  <SubmitButton handleSubmit={handleSubmit} />
                  {formSwitchLink()}
                </View>
              </View>
            );
          }}
        </Formik>
      );
    };

InputFormik

class InputFormik extends React.Component {
  constructor(props) {
    super(props);
    this.refProp = React.createRef();
  }
  render() {
    const { formikKey, formikProps, pwdStrength, ...rest } = this.props;
    const errorMessage = formikProps.errors[formikKey];
    const haveErrors =
      formikProps.errors[formikKey] && (formikProps.touched[formikKey] || formikProps.isSubmitting);
    return (
      <Input
        ref={(inputRef) => (this.refProp = inputRef)}
        onChangeText={formikProps.handleChange(formikKey)}
        onBlur={formikProps.handleBlur(formikKey)}
        placeholderTextColor={config.ThemeColors.text.label}
        labelStyle={controlLabel.normal}
        value={formikProps.values[formikKey]}
        errorMessage={haveErrors ? errorMessage : null}
        errorProps={{ accessibilityLiveRegion: 'polite' }}
        errorStyle={errorText}
        inputStyle={haveErrors ? textbox.error : textbox.normal}
        inputContainerStyle={haveErrors ? textbox.containerError : null}
        containerStyle={inputContainer}
        {...rest}
      />
    );
  }
}
export default InputFormik;
1

1 Answers

0
votes

I think the root cause here might be that you're 'calling' the loginFormFormik / registerForm as functions, rather than rendering them as components. This means that React sees the Formik components returned from each function as the same component.

If you 'render' the components it should treat them separately, so create a new reference to a component when this.props.session.loginForm switches, then remount with the new initial values.

<View style={styles.section}>
    {this.props.session.loginForm ? <loginFormFormik /> : <registerForm />}
</View>