mapDispatchToProps 类型挑战typescript react-redux

问题描述

我无法弄清楚我的 mapdispatchToProps 的类型。在 SignInComponent const mapdispatchToProps 中检查以下内容。 看起来很简单,因为函数将 signIn() 作为参数,我可以从谁那里获得类型。但是我无法弄清楚。

这是我的 autAction.ts:

import firebase from 'firebase/app'
import { dispatch } from 'react';

type AuthAction = {
  type: string,err?: unkNown
}

export const signIn = (credentials: {email:string,password:string}) => {
  return (dispatch: dispatch<AuthAction>) => {
    firebase.auth().signInWithEmailAndPassword(
      credentials.email,credentials.password
    ).then(() => {
      dispatch({ type: 'LOGIN_SUCCESS'})
    }).catch((err) => {
      dispatch({ type: 'LOGIN_ERROR',err})
    });
  }
}

这是我的登录组件:

import React,{ BaseSyntheticEvent,Component } from 'react'
import { connect } from 'react-redux';
import { signIn } from '../../store/actions/authActions';


type IConnecteddispatch = {
  signIn: typeof signIn
}

interface IMyComponentProps {
  signIn: (credentials: {email:string,password:string}) => void;
}

class SignIn extends Component<IMyComponentProps> {
  state = {
    email:'',password:''
  }

  handleChange = (e:BaseSyntheticEvent) => {
    this.setState({
      [e.target.id]: e.target.value
    });
  }

  handleSubmit = (e:BaseSyntheticEvent) => {
    e.preventDefault();
    //console.log(this.state);
    this.props.signIn(this.state);
  }

  render() {
    return (
      <div className="container">
        <form onSubmit={this.handleSubmit} className="white">
          <h5 className="grey-text text-darken-3">Sing In</h5>
          <div className="input-field">
            <label htmlFor="email">Email</label>
            <input type="email" id="email" onChange={this.handleChange}/>
          </div>
          <div className="input-field">
            <label htmlFor="password">Password</label>
            <input type="password" id="password" onChange={this.handleChange}/>
          </div>
          <div className="input-field">
            <button className="btn pink lighten-1 z-depth-0">Login</button>
          </div>
        </form> 
      </div>
    )
  }
}

type AuthAction = {
  type:string,err?: unkNown
}

const mapdispatchToProps = (dispatch: any): IConnecteddispatch  => { //TYPE CHALLENGE HERE. 
  return {
    signIn: (credentials:{ email:string,password:string}) => dispatch(signIn(credentials))
  }
}

export default connect<React.FunctionComponent>(null,mapdispatchToProps)(SignIn)

解决方法

试试这个:

import React,{ BaseSyntheticEvent,Component } from 'react'
import { connect } from 'react-redux';
import { signIn } from '../../store/actions/authActions';

interface IMyComponentProps {
  signIn: typeof signIn
}

class SignIn extends Component<IMyComponentProps> {
  state = {
    email:'',password:''
  }

  handleChange = (e:BaseSyntheticEvent) => {
    this.setState({
      [e.target.id]: e.target.value
    });
  }

  handleSubmit = (e:BaseSyntheticEvent) => {
    e.preventDefault();
    //console.log(this.state);
    this.props.signIn(this.state);
  }

  render() {
    return (
      <div className="container">
        <form onSubmit={this.handleSubmit} className="white">
          <h5 className="grey-text text-darken-3">Sing In</h5>
          <div className="input-field">
            <label htmlFor="email">Email</label>
            <input type="email" id="email" onChange={this.handleChange}/>
          </div>
          <div className="input-field">
            <label htmlFor="password">Password</label>
            <input type="password" id="password" onChange={this.handleChange}/>
          </div>
          <div className="input-field">
            <button className="btn pink lighten-1 z-depth-0">Login</button>
          </div>
        </form> 
      </div>
    )
  }
}

export default connect(null,{ signIn } )(SignIn)
,

如@liamgbs 的回答所示,您的 mapDispatchToProps 并不是真正必要的,但我确实想回答您关于打字稿问题的问题。

mapDispatchToProps 是一个函数,它接受 dispatch 作为参数并返回一个带有键的 props 对象。所以类型本质上是(dispatch: Dispatch)

问题是 Dispatch 在这里使用哪个定义,因为多个包有自己的类型。来自 Dispatchreactredux 更基本的定义期望 dispatch 只会用普通的 action 对象调用。 signIn 动作创建者的返回值是 dispatch 的函数(“thunk”)。因此,您需要使用 redux-thunk 包中的类型。

{signIn: typeof signIn} 也不完全正确,因为您正在调用 signIn 而不是仅仅返回它。实际接口是您的 IMyComponentProps,其中 signIn 是一个 void 函数。

import { ThunkDispatch } from "redux-thunk";

interface LoginCredentials {
  email: string;
  password: string;
}

interface IMyComponentProps {
  signIn: (credentials: LoginCredentials) => void;
}

const mapDispatchToProps = ( dispatch: ThunkDispatch<any,never,AuthAction> ): IMyComponentProps => {
  return {
    signIn: (credentials: LoginCredentials) => dispatch(signIn(credentials))
  };
};

令人讨厌的是,ThunkDispatch 要求您设置所有三个泛型。第一个 any 代表您的 redux 状态的类型,因此您可以根据需要将其替换为实际类型。 never 是您未使用的操作创建器中的额外参数。