Reputation: 2312
Goal: create an action that returns a promise, that takes arguments, and utilizes dispatch.
the best I've come up with for the action:
export const loginAction = (arg1, arg2) => {
return (dispatch) => {
dispatch({type: types.SOME_TYPE});
return new Promise((resolve, reject) => {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
loginSuccess(dispatch, user);
resolve(user)
}
}).catch(error => reject(error))
})
}
}
the way I want to implement it:
login = () => {
this.props.loginAction(this.state.email, this.state.password)
.then(user => {
if (user) {
this.props.navigation.navigate("App")
}
}
}
LoginScreen:
import React from 'react';
import { loginUser, logoutUser, resetAuth, sendPwdLink } from '../actions';
import { connect } from 'react-redux';
// other imports...
const { width } = Dimensions.get('window');
class LoginScreen extends React.Component {
constructor (props) {
super(props);
this.state = {
email: '',
password: ''
};
}
goToRegister = () => {
this.props.resetAuth();
this.props.navigation.navigate('Register');
};
goToLearnMore = () => {
this.props.navigation.navigate('LearnMore');
};
login = () => {
this.props.loginUser(this.state.email, this.state.password).then((user) => {
user ? this.props.navigation.navigate('App') : null;
});
};
render () {
return (
<View style={styles.container}>
<View style={{ alignItems: 'center' }}>
<Components.TransparentInput
placeholder={'Email Address...'}
style={{ width: width * 0.5, margin: width * 0.015, fontFamily: Fonts.QUICKSAND }}
placeholderColor={'white'}
onChangeText={(text) => {
this.setState({ email: text });
}}
/>
<Components.TransparentInput
placeholder={'Password...'}
secureTextEntry={true}
style={{ width: width * 0.5, margin: width * 0.015, fontFamily: Fonts.QUICKSAND }}
placeholderColor={'white'}
onChangeText={(text) => {
this.setState({ password: text });
}}
/>
<TouchableWithoutFeedback onPress={() => this.sendPwdLink(this.state.email)}>
<Text
style={{
fontSize: 14,
color: 'white',
textDecorationLine: 'underline',
fontFamily: Fonts.QUICKSAND
}}
>
Forgot password?
</Text>
</TouchableWithoutFeedback>
</View>
<View>
<Components.Button
type={'primary'}
text={'Login'}
onPress={this.login}
style={{ width: width * 0.4, margin: width * 0.015 }}
fontSize={18}
/>
<Components.Button
style={{ width: width * 0.35, margin: width * 0.015 }}
type={'secondary'}
text={'Register'}
onPress={this.goToRegister}
fontSize={18}
/>
</View>
<TouchableWithoutFeedback onPress={this.goToLearnMore}>
<Text
style={{
fontSize: 16,
color: 'white',
textDecorationLine: 'underline',
fontFamily: Fonts.QUICKSAND
}}
>
What is Slide?
</Text>
</TouchableWithoutFeedback>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-evenly',
alignItems: 'center',
backgroundColor: Colors.PRIMARY_DARK
}
});
const mapStateToProps = ({ auth }) => {
const { authenticated, loading, error, user } = auth;
return { authenticated, loading, error, user };
};
const mapDispatchToProps = { loginUser, logoutUser, resetAuth, sendPwdLink };
export default connect(mapStateToProps, mapDispatchToProps)(LoginScreen);
But this doesn't work, it results in an error: TypeError: undefined is not an object...evaluating this.props.loginAction(arg1, arg2)
EDIT: I believe the actions have access to dispatch
through the mapDispatchToProps function. I could be wrong. I dont totally understand that part of the action function but it didnt work without it.
What changes can be made to fix this?
Upvotes: 0
Views: 84
Reputation: 1300
[EDITED]
First of all you need redux-thunk.
In place where you create store you need to add this.
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
const store = createStore(rootReducer, applyMiddleware(thunk));
your loginAction
is correct.
Your just need to update mapDispatchToProps
import { bindActionCreators } from 'redux'; // dont forget to import this
const mapDispatchToProps = dispatch =>
bindActionCreators({
loginUser,
logoutUser,
resetAuth,
sendPwdLink,
}, dispatch);
bindActionCreators
- Turns an object whose values are action creators, into an object with the same keys, but with every action creator wrapped into a dispatch call so they may be invoked directly.
so bindActionCreators does next:
const actions = { loginUser };
const bindActions = Object.keys(actions).map((action) => dispatch(action));
link to proof
next when you call in your code your function which is loginUser
it dispatches your function which comes to redux-thunk middleware and after redux-thunk check it runs your function with next arguments:
your_action_function(dispatch, getState, extraArgument);
I hope now it's clear for you
Upvotes: 1