已将项目从JavaScript转换为TypeScript。单击组件的登录按钮时,onSumbit甚至会触发,但不会调度redux操作。原始的JavaScript版本可以正常工作。该项目在构建时可以正常编译,没有错误。
TypeScript文件:
interface IErrors {
email: string | undefined;
password: string | undefined;
}
interface IUser {
email: string;
password: string;
}
interface IState {
email: string;
password: string;
[key: string]: string;
}
interface IReduxProps {
errors: IErrors;
}
interface IDispatchProps {
loginUser: (user: IUser, history: any) => (dispatch: any) => Promise<any>;
clearErrors: () => { type: string };
}
interface IProps extends IReduxProps {
loginUser: (user: IUser, history: any) => (dispatch: any) => Promise<any>;
clearErrors: () => { type: string };
}
export class Login extends React.Component<IProps, IState> {
state = {
email: '',
password: '',
};
onSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
const user = {
email: this.state.email,
password: this.state.password,
};
this.props.loginUser(user, history);
};
onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ [e.target.name]: e.target.value });
};
componentWillUnmount() {
this.props.clearErrors();
}
render() {
return (
<div className={styles.page}>
<div className={styles.content}>
<h1 className={styles.title}>Login</h1>
<form className={styles.form} onSubmit={this.onSubmit}>
<div className={styles.inputGroup}>
<label className={styles.label} htmlFor="email">
Email
</label>
<input
className={classNames(styles.input, {
[styles.inputError]:
this.props.errors && this.props.errors.email,
})}
type="text"
name="email"
id="email"
value={this.state.email}
onChange={this.onChange}
autoComplete="email"
/>
{this.props.errors && this.props.errors.email ? (
<p className={styles.error}>{this.props.errors.email}</p>
) : null}
</div>
<div className={styles.inputGroup}>
<label className={styles.label} htmlFor="password">
Password
</label>
<input
className={classNames(styles.input, {
[styles.inputError]:
this.props.errors && this.props.errors.password,
})}
type="password"
name="password"
id="password"
value={this.state.password}
onChange={this.onChange}
autoComplete="password"
/>
{this.props.errors && this.props.errors.password ? (
<p className={styles.error}>{this.props.errors.password}</p>
) : null}
</div>
<button className={styles.button} type="submit">
Login
</button>
</form>
<Link className={styles.link} to="/register">
I need an account
</Link>
</div>
</div>
);
}
}
// TODO: change state to match redux state interface
const mapStateToProps = (state: any): IReduxProps => ({
errors: state.errors,
});
const mapDispatchToProps = (): IDispatchProps => ({
loginUser,
clearErrors,
});
export default connect(mapStateToProps, mapDispatchToProps)(Login);
还原操作:
export const loginUser = (userData, history) => dispatch => {
return axios
.post('/api/login', userData)
.then(res => {
const { token, id } = res.data;
localStorage.setItem('token', token);
setAuthToken(token);
dispatch({ type: 'LOGIN', payload: { id, token } });
history.push('/dashboard');
dispatch({ type: 'CLEAR_ERRORS' });
})
.catch(err =>
dispatch({
type: 'GET_ERRORS',
payload: err.response.data,
}),
);
};
任何帮助将不胜感激
答案 0 :(得分:2)
我认为这是因为您实际上并没有在任何地方使用“调度”。
将bindActionCreators添加到您的mapDispatchToProps
function mapDispatchToProps(dispatch: any, ownProps: IOwnProps): IDispatchProps {
return bindActionCreators(
{
loginUser,
clearErrors,
},
dispatch
);
}
或者您可以使用
const mapDispatchToProps = dispatch => {
return {
loginUser: (userData, history) => dispatch(loginUser(userData, history))
}
}
使用“动作创建者”时,这都是必需的