0

我无法弄清楚我的 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)
4

2 回答 2

2

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

mapDispatchToProps是一个dispatch以参数为参数并返回 props 的键控对象的函数。所以类型本质上是(dispatch: Dispatch).

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

{signIn: typeof signIn}也不完全正确,因为您正在调用 signIn而不是仅仅返回它。实际的接口是 your IMyComponentProps, wheresignIn是一个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是您未使用的动作创建器中的额外参数。

于 2021-02-01T20:23:17.257 回答
1

试试这样:

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)
于 2021-02-01T17:36:31.300 回答