0

I'm a bit new to react, react-native, react-redux, and react-thunk and am encountering this strange issue which I can't explain.

I have a sign-in component that uses a thunk to authenticate a user. I mapDispatchToProps and apply it to the component but for some reason, every time the component renders, it triggers the thunk and then after every keypress in either input field, the thunk is also triggered. this creates countless calls to the authentication API which all fail.

What would cause this behavior?

const SignIn = ({navigation, signIn}: any): React.ReactElement => {
  const [username, setUsername] = React.useState<string>('');
  const [password, setPassword] = React.useState<string>('');
  const [passwordVisible, setPasswordVisible] = React.useState<boolean>(false);

  const onForgotPasswordButtonPress = (): void => {
    navigation && navigation.navigate('Forgot Password');
  };

  const onPasswordIconPress = (): void => {
    setPasswordVisible(!passwordVisible);
  };

  const passwordInput = useRef() as React.MutableRefObject<any>;

  return (
    <KeyboardAvoidingView>
      <ImageOverlay
        style={styles.container}
        source={require('../assets/images/image-background3.jpg')}>
        <SafeAreaView style={styles.container}>   
          <View style={styles.formContainer}>
            <Input
              status="control"
              placeholder="Username"
              autoCapitalize={'none'}
              autoCompleteType={'off'}
              autoCorrect={false}
              autoFocus={false}
              icon={PersonIcon}
              value={username}
              onChangeText={setUsername}
              returnKeyType={'next'}
              blurOnSubmit={false}
              onSubmitEditing={() => passwordInput.current.focus()}
            />
            <Input
              ref={passwordInput}
              style={styles.passwordInput}
              status="control"
              placeholder="Password"
              autoCapitalize={'none'}
              autoCompleteType={'off'}
              autoCorrect={false}
              icon={passwordVisible ? EyeIcon : EyeOffIcon}
              value={password}
              secureTextEntry={!passwordVisible}
              onChangeText={setPassword}
              onIconPress={onPasswordIconPress}
              onSubmitEditing={() => signIn(username, password)}
            />
            <View style={styles.forgotPasswordContainer}>
              <Button
                style={styles.forgotPasswordButton}
                appearance="ghost"
                status="control"
                onPress={onForgotPasswordButtonPress}>
                Forgot your password?
              </Button>
            </View>
          </View>
          <Button
            style={styles.signInButton}
            status="control"
            size="large"
            disabled={username.length === 0 || password.length === 0}
            onPress={signIn(username, password)}>
            Sign In
          </Button>
        </SafeAreaView>
      </ImageOverlay>
    </KeyboardAvoidingView>
  );
};

const mapDispatchToProps = (dispatch: any) => ({
  signIn: (username: string, password: string) =>
    dispatch(signInThunk(username, password)),
});

export const SignInScreen = connect(
  null,
  mapDispatchToProps,
)(SignIn);

thunk:

export const signInThunk = (username: string, password: string) => {
  return async (dispatch: any) => {

    try {
      dispatch(isLoading(true));

      const userData = await fetch(Providers.auth, {...})
        .then(response => response.json())
        .then(() => dispatch(isLoading(false)));

      if(userData.token){
       dispatch(signInAction(userData.token));
       dispatch(updateProfileAction(userData));
      }

      dispatch(isLoading(false));
    } catch (error) {
      console.error(error);
    }
  };
};
kisonay
  • 331
  • 5
  • 14
  • Have try to change `onPress={signIn(username, password)}` to `onPress={() => signIn(username, password)}` – Kishan Bharda Feb 05 '20 at 13:39
  • @KishanBharda that was it, something so simple. please answer the question and I will mark it as correct. is there any particular reason why it must be a function within a function? – kisonay Feb 05 '20 at 14:04
  • I posted as answer. And this is just js syntax. I also don't know more about this reason. – Kishan Bharda Feb 05 '20 at 14:10

1 Answers1

1

This is common mistake, just change :

onPress={signIn(username, password)}

to

onPress={() => signIn(username, password)}
Kishan Bharda
  • 3,990
  • 3
  • 18
  • 42