As a newcomer to react, react-native, react-redux, and react-thunk, I find myself facing a strange issue that is puzzling me.
The sign-in component I have implemented uses a thunk for user authentication. I have mapDispatchToProps and applied it to the component, but for some reason, every time the component renders, the thunk is triggered. Additionally, each keypress in either input field also triggers the thunk, leading to multiple calls to the authentication API that all end up failing.
What could be causing this unexpected 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);
}
};
};