简体   繁体   English

React Typescript 组件未正确调度 redux 操作

[英]React Typescript component not properly dispatching a redux action

Have been converted a project from JavaScript to TypeScript.已将一个项目从 JavaScript 转换为 TypeScript。 When the login button of the component is clicked the onSumbit even fires but the redux action is not dispatched.当单击组件的登录按钮时,onSumbit 甚至会触发,但不会调度 redux 操作。 The vanilla JavaScript version of this works fine.这个的香草 JavaScript 版本工作正常。 The project does compile normally when built, with no errors.该项目在构建时确实编译正常,没有错误。

The TypeScript file:打字稿文件:

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);

The redux action:还原动作:

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,
            }),
        );
};

Any help would be much appreciated任何帮助将非常感激

I think this is because you are not actually using "dispatch" anywhere.我认为这是因为您实际上并没有在任何地方使用“调度”。

Add bindActionCreators to your mapDispatchToProps将 bindActionCreators 添加到您的 mapDispatchToProps

function mapDispatchToProps(dispatch: any, ownProps: IOwnProps): IDispatchProps {
  return bindActionCreators(
    {
       loginUser,
       clearErrors,
    },
    dispatch
  );
}

or you could use或者你可以使用

const mapDispatchToProps = dispatch => {
  return {
    loginUser: (userData, history) => dispatch(loginUser(userData, history))
  }
}

This is all needed as you are using 'action creators'当您使用“动作创建者”时,这一切都是必需的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM