mapDispatchToProps 类型挑战(typescript react-redux)

mapDispatchToProps type challenge (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 作为参数,returns 是道具的键控对象。所以类型本质上是 (dispatch: Dispatch).

问题是 Dispatch 在这里使用的定义,因为多个包都有自己的类型。 reactreduxDispatch 的更基本定义预计 dispatch 将仅使用普通操作对象调用。来自 signIn 动作创建者的 return 值是 dispatch 的函数(“thunk”)。所以你需要使用 redux-thunk 包中的类型。

{signIn: typeof signIn} 也不完全正确,因为您正在 调用 signIn 而不仅仅是 return 调用它。实际界面是您的 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 是您未使用的 action creator 中的额外参数。