1

I have developed a react native application. In there I am updating a state variable through redux-thunk action dispatch. Now what I want is I want to navigate to another component when It is updated. How I have written is like this.

  useEffect(() => {
    _navigateOnSuccessOtp(props.navigation);
  }, [props.success, props.navigation]);

This is navigated to next view even when navigation is changed because It also has been added as a dependency to this effect. This is my full code of the component.

import React, {useEffect} from 'react';
import {
  View,
  TouchableOpacity,
  KeyboardAvoidingView,
  Switch,
  TextInput,
  BackHandler,
} from 'react-native';
import I18n from 'react-native-i18n';
import {Formik} from 'formik';
import * as Yup from 'yup';
import {connect} from 'react-redux';
import {signinActions} from '_store/actions';
import SubmitButton from '_components/submitButton/';
import AppText from '_components/appText';
import {strings} from '_translations/i18n';
import styles from './loginstyle';
import Icon from 'react-native-vector-icons/FontAwesome';

const keepMe = (e) => {
  console.log(e);
};

const handleBackButton = () => {
  return true;
};

const _onPress = (values, sendOTP) => {
  console.log(values.mobileNo);
  sendOTP(values.mobileNo);
  // navigation.navigate('Otp');
};

const _navigateOnSuccessOtp = (navigation) => {
  navigation.navigate('Otp');
};

const changeLanguage = (navigate) => {
  navigate.navigate('Home');
};

const getCurrentLocale = () => {
  let locale;
  locale = I18n.locale;
  if (locale === 'en') {
    return <AppText styles={styles.bottomLinkText}>English</AppText>;
  } else if (locale === 'ta') {
    return <AppText styles={styles.bottomLinkText}>தமிழ்</AppText>;
  }
};

const Login = (props) => {
  useEffect(() => {
    BackHandler.addEventListener('hardwareBackPress', handleBackButton);

    return () => {
      BackHandler.removeEventListener('hardwareBackPress', handleBackButton);
    };
  }, []);

  useEffect(() => {
    _navigateOnSuccessOtp(props.navigation);
  }, [props.success, props.navigation]);

  return (
    <KeyboardAvoidingView style={{flex: 1}} enabled>
      <View style={styles.signinView}>
        <View style={styles.signinTitleView}>
          <AppText styles={styles.signinTitle}>
            {strings('login.title')}
          </AppText>
        </View>
        <View style={styles.colempty} />
        <View style={styles.signIn}>
          <View style={styles.signInContainer}>
            <AppText styles={styles.loginFormTitle}>
              {strings('login.title')}
            </AppText>
            <View style={styles.formContainer}>
              <Formik
                initialValues={{
                  mobileNo: '',
                  toggle: true,
                }}
                validationSchema={Yup.object({
                  mobileNo: Yup.string().required('Mobile number required'),
                })}
                onSubmit={(values, formikActions) => {
                  _onPress(values, props.sendOTP);
                  setTimeout(() => {
                    formikActions.setSubmitting(false);
                  }, 500);
                }}>
                {(formprops) => (
                  <View>
                    <View
                      style={
                        (!formprops.touched.mobileNo
                          ? styles.inputView
                          : null) ||
                        (formprops.values.mobileNo && !formprops.errors.mobileNo
                          ? styles.validInputView
                          : null) ||
                        (formprops.touched.mobileNo && formprops.errors.mobileNo
                          ? styles.inputViewError
                          : null)
                      }>
                      <TextInput
                        style={styles.textField}
                        placeholder={strings('login.mobile')}
                        placeholderTextColor="#bbbbbb"
                        value={formprops.values.mobileNo}
                        onChangeText={formprops.handleChange('mobileNo')}
                        onBlur={formprops.handleBlur('mobileNo')}
                        keyboardType="numeric"
                      />
                      {formprops.touched.mobileNo &&
                      formprops.errors.mobileNo ? (
                        <Icon name="times" size={20} style={styles.errorIcon} />
                      ) : null}
                      {formprops.touched.mobileNo &&
                      formprops.values.mobileNo ? (
                        <Icon name="check" size={20} style={styles.validIcon} />
                      ) : null}
                    </View>
                    {formprops.touched.mobileNo && formprops.errors.mobileNo ? (
                      <View style={styles.errorMessage}>
                        <AppText styles={styles.errorMessageText}>
                          {formprops.errors.mobileNo}
                        </AppText>
                      </View>
                    ) : null}
                    <View style={styles.togglebuttoncontainer}>
                      <View style={styles.toggleTextView}>
                        <AppText styles={styles.toggleText}>
                          {strings('login.keep-login')}
                        </AppText>
                      </View>
                      <View style={styles.toggleView}>
                        <Switch
                          trackColor={{false: '#dddddd', true: '#c1d6ee'}}
                          thumbColor={{false: '#ffffff', true: '#007aff'}}
                          ios_backgroundColor="#dddddd"
                          onValueChange={(value) =>
                            formprops.setFieldValue('toggle', value)
                          }
                          value={formprops.values.toggle}
                          style={styles.toggle}
                        />
                      </View>
                    </View>
                    <SubmitButton
                      onpress={formprops.handleSubmit}
                      btext={strings('login.button-text')}
                    />
                  </View>
                )}
              </Formik>
            </View>
          </View>
        </View>
        <View style={styles.hr} />
        <View style={styles.signInBottomContainer}>
          <View style={styles.signInBottomView}>
            <View style={styles.signInBottomContainerTextView}>
              <AppText styles={styles.signInBottomContainerText}>
                {strings('login.language-change')}?
              </AppText>
            </View>
            <View style={styles.signInBottomLinkView}>
              <TouchableOpacity
                onPress={() => changeLanguage(props.navigation)}>
                {getCurrentLocale()}
              </TouchableOpacity>
            </View>
          </View>
        </View>
      </View>
    </KeyboardAvoidingView>
  );
};

const mapStateToProps = (state) => {
  console.log(state);
  return {
    success: state.signin.success,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    sendOTP: (number) => dispatch(signinActions.sendOtpActionCreator(number)),
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(Login);

I tried a lot to figure out how to do it correctly but I was unable to do so. So can someone help me with this problem? Thank you.

1 Answers1

0

Since , _navigateOnSuccessOtp only uses navigation.navigate you can simply pass props.navigation.navigate as a dependency for useEffect and also as an argument to the function. Now navigate does not change and hence your useEffect won't be triggered unnecessarily.

const _navigateOnSuccessOtp = (navigate) => {
 navigate('Otp');
};

.....

useEffect(() => {
  _navigateOnSuccessOtp(props.navigation.navigate);
}, [props.success, props.navigation.navigate]);

You could also remove props.navigation from the dependency as you don't want useEffect to trigger on props.navigation change. Please check this post for more details: How to fix missing dependency warning when using useEffect React Hook?

Jagrati
  • 11,474
  • 9
  • 35
  • 56