I am not able to figure out the type of my mapDispatchToProps. Check below in the SignInComponent const mapDispatchToProps
.
Seems simple as the functions takes signIn() as a parameter, from whom type I have availble. However I was not able to figure that out.
This is my 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})
});
}
}
And this is my SignIn component:
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)
As shown in @liamgbs' answer, your
mapDispatchToProps
isn't really necessary, but I do want to answer your questions regarding the typescript issues.mapDispatchToProps
is a function which takesdispatch
as an argument and returns a keyed object of props. So the type is essentially(dispatch: Dispatch)
.The question is which
Dispatch
definition to use here, as multiple packages have their own typings for it. The more basic definitions ofDispatch
fromreact
andredux
expect thatdispatch
will only be called with a plain action object. The return value from yoursignIn
action creator is instead a function ofdispatch
(a "thunk"). So you need to use typings from theredux-thunk
package.{signIn: typeof signIn}
is also not quite right because you are callingsignIn
rather than just returning it. The actual interface is yourIMyComponentProps
, wheresignIn
is avoid
function.Annoyingly,
ThunkDispatch
requires you to set all three generics. That firstany
represents the type of your redux state, so you could replace that with an actual type if you want. Thenever
is the extra args in your action creator which you aren't using.