如何创建带有 returns 承诺的参数的操作?
How to create an action with arguments that returns a promise?
目标:创建一个 returns 承诺的操作,该操作接受参数并利用分派。
我想出的最好的动作:
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))
})
}
}
我想实现的方式:
login = () => {
this.props.loginAction(this.state.email, this.state.password)
.then(user => {
if (user) {
this.props.navigation.navigate("App")
}
}
}
登录屏幕:
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);
但这不起作用,会导致错误:TypeError: undefined is not an object...evaluating this.props.loginAction(arg1, arg2)
编辑:我相信动作可以通过 mapDispatchToProps 函数访问 dispatch
。我可能是错的。我不完全理解动作功能的那一部分,但没有它就无法工作。
可以进行哪些更改来解决此问题?
[编辑]
首先你需要redux-thunk.
在你创建商店的地方你需要添加这个。
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
const store = createStore(rootReducer, applyMiddleware(thunk));
你的 loginAction
是正确的。
你只需要更新mapDispatchToProps
import { bindActionCreators } from 'redux'; // dont forget to import this
const mapDispatchToProps = dispatch =>
bindActionCreators({
loginUser,
logoutUser,
resetAuth,
sendPwdLink,
}, dispatch);
bindActionCreators
- 将值为 action creators 的对象转换为具有相同键的对象,但每个 action creator 都包装在一个调度调用中,以便可以直接调用它们。
接下来 bindActionCreators 会做:
const actions = { loginUser };
const bindActions = Object.keys(actions).map((action) => dispatch(action));
link 到 proof
下一步当你在你的代码中调用你的函数时 loginUser
它调度你的函数,它到达 redux-thunk 中间件,在 redux-thunk check 之后,它使用下一个参数运行你的函数:
your_action_function(dispatch, getState, extraArgument);
我希望你现在明白了
目标:创建一个 returns 承诺的操作,该操作接受参数并利用分派。
我想出的最好的动作:
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))
})
}
}
我想实现的方式:
login = () => {
this.props.loginAction(this.state.email, this.state.password)
.then(user => {
if (user) {
this.props.navigation.navigate("App")
}
}
}
登录屏幕:
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);
但这不起作用,会导致错误:TypeError: undefined is not an object...evaluating this.props.loginAction(arg1, arg2)
编辑:我相信动作可以通过 mapDispatchToProps 函数访问 dispatch
。我可能是错的。我不完全理解动作功能的那一部分,但没有它就无法工作。
可以进行哪些更改来解决此问题?
[编辑]
首先你需要redux-thunk.
在你创建商店的地方你需要添加这个。
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
const store = createStore(rootReducer, applyMiddleware(thunk));
你的 loginAction
是正确的。
你只需要更新mapDispatchToProps
import { bindActionCreators } from 'redux'; // dont forget to import this
const mapDispatchToProps = dispatch =>
bindActionCreators({
loginUser,
logoutUser,
resetAuth,
sendPwdLink,
}, dispatch);
bindActionCreators
- 将值为 action creators 的对象转换为具有相同键的对象,但每个 action creator 都包装在一个调度调用中,以便可以直接调用它们。
接下来 bindActionCreators 会做:
const actions = { loginUser };
const bindActions = Object.keys(actions).map((action) => dispatch(action));
link 到 proof
下一步当你在你的代码中调用你的函数时 loginUser
它调度你的函数,它到达 redux-thunk 中间件,在 redux-thunk check 之后,它使用下一个参数运行你的函数:
your_action_function(dispatch, getState, extraArgument);
我希望你现在明白了