Javascript Redux+;TypeScript和mapDispatchToProps
这应该很容易,但目前我还没有做到,但我觉得这应该是一个简单的解决办法。我目前正在将Javascript Redux+;TypeScript和mapDispatchToProps,javascript,reactjs,typescript,redux,react-redux,Javascript,Reactjs,Typescript,Redux,React Redux,这应该很容易,但目前我还没有做到,但我觉得这应该是一个简单的解决办法。我目前正在将redux与typescript一起使用,并将redux-thunk用于异步动作创建者 设置很简单。以下是我用于登录的代码: export function requestAuthenticationAsync(email: string, password: string) { return (dispatch: ThunkDispatch<IState, undefined, IAction>
redux
与typescript
一起使用,并将redux-thunk
用于异步动作创建者
设置很简单。以下是我用于登录的代码:
export function requestAuthenticationAsync(email: string, password: string) {
return (dispatch: ThunkDispatch<IState, undefined, IAction>): Promise<void> => {
dispatch(requestAuthentication());
return postAuthentication(email, password).then((response) => {
dispatch(receiveAuthentication());
return response.json();
}).then((data) => {
dispatch(receiveUser(data));
});
};
}
但是,当我使用connect
和mapDispatchToProps
fromreact redux
时,如下所示:
import './Gateway.scss';
import * as React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { requestAuthenticationAsync } from './actions';
import { withRouter } from 'react-router-dom';
const mapDispatchToProps = (dispatch) => {
return {
requestAuthenticationAsync: bindActionCreators(requestAuthenicationAsync, dispatch)
};
};
const mapStateToProps = (state) => {
return {
authenticated: state.authentication.authenticated
};
};
class Gateway extends React.Component<{
authenticated: boolean;
requestAuthenticationAsync: typeof requestAuthenticationAsync;
}, {
email: string;
password: string;
}> {
constructor(props) {
super(props);
this.state = {
email: '',
password: ''
};
}
onGatewaySubmit = (event) => {
event.preventDefault();
const { requestAuthenticationAsync } = this.props;
const { email, password } = this.state;
requestAuthenticationAsync(email, password).then(() => {
console.log('done');
});
};
onEmailValueChange = (event) => {
this.setState({
email: event.target.value
});
};
onPasswordValueChange = (event) => {
this.setState({
password: event.target.value
});
};
render() {
return (
<div id='gateway'>
<form onSubmit={ this.onGatewaySubmit }>
<input
className='email'
onChange={ this.onEmailValueChange }
placeholder='email'
type='text' />
<input
className='password'
onChange={ this.onPasswordValueChange }
placeholder='password'
type='password' />
<input type='submit' value='Submit' />
</form>
</div>
);
}
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Gateway));
导入“/Gateway.scss”;
从“React”导入*作为React;
从“redux”导入{bindActionCreators};
从'react redux'导入{connect};
从“./actions”导入{requestAuthenticationAsync};
从“react router dom”导入{withRouter};
const mapDispatchToProps=(调度)=>{
返回{
requestAuthenticationAsync:bindActionCreators(requestAuthenticationAsync,dispatch)
};
};
常量mapStateToProps=(状态)=>{
返回{
已验证:state.authentication.authenticated
};
};
类网关扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
电子邮件:“”,
密码:“”
};
}
onGatewaySubmit=(事件)=>{
event.preventDefault();
const{requestAuthenticationAsync}=this.props;
const{email,password}=this.state;
requestAuthenticationAsync(电子邮件、密码)。然后(()=>{
console.log('done');
});
};
onEmailValueChange=(事件)=>{
这是我的国家({
电子邮件:event.target.value
});
};
onPasswordValueChange=(事件)=>{
这是我的国家({
密码:event.target.value
});
};
render(){
返回(
);
}
}
使用路由器导出默认值(连接(mapStateToProps、mapDispatchToProps)(网关));
我得到以下错误:
TS2339: Property 'then' does not exist on type '(dispatch: ThunkDispatch<IState, undefined, IAction>) => Promise<void>'.
TS2339:type'(dispatch:ThunkDispatch)=>Promise上不存在属性“then”。
有什么好处?在这种情况下,我如何让TypeScript满意,这样我就可以在
中使用承诺。然后?我想检查一下我理解了什么,因为我不能写评论
如果您像这样在代码的onGatewaySubmit
函数中调用requestAuthenticationAsync
requestAuthenticationAsync(email, password).then(() => {
console.log('done');
});
我觉得您正在调用下面的已调度函数
dispatch(requestAuthenticationAsync)(email, password).then(() => {
// navigate somewhere
});
不象你写的那样
dispatch(requestAuthenticationAsync('email', 'password')).then(() => {
// navigate somewhere
});
这可能有点离题,但您能解释一下流程吗?问题的根本原因是redux-thunk
是由redux
执行的中间件,因此它调用函数(thunk)并返回值。然而,TypeScript并没有“意识到”正在发生的情况,所以无法正确地键入它(不需要额外的工作)
redux thunk
包(此时)实际上附带类型定义。然而,它的类型定义有很多重大改进,但没有发布。在3.0版本中,它们将被删除并移动到DefinitelyTyped(可通过@types/redux-thunk
安装)
但在此之前,您可以自己设置类型。如果需要,则类型定义相对较多
要使用这些文件(在它们以新版本的redux thunk
或DefinitelyTyped发布之前),您可以使用以下内容创建类型文件(例如:types.d.ts
):
从“redux”导入{ActionCreatorsMapObject};
从“redux-thunk”导入{ThunkAction};
/**
*中间件改变了Redux行为,因此这里重载
*/
声明模块“redux”{
/**
*bindActionCreators redux函数的重载,返回预期响应
*从恶作剧中
*/
函数bindActionCreators<
通过查看TActionCreators扩展ActionCreatorsMapObject
,TActionCreators扩展了ActionCreatorsMapObject)
现在应该正确键入This.props.requestAuthenticationAsync
,以便在组件中使用
onGatewaySubmit = event => {
event.preventDefault();
const { requestAuthenticationAsync } = this.props;
const { email, password } = this.state;
// Type:
// (email: string, password: string) => Promise<void>
requestAuthenticationAsync(email, password).then(() => {
console.log("done");
});
};
onGatewaySubmit=事件=>{
event.preventDefault();
const{requestAuthenticationAsync}=this.props;
const{email,password}=this.state;
//类型:
//(电子邮件:string,密码:string)=>承诺
requestAuthenticationAsync(电子邮件、密码)。然后(()=>{
控制台日志(“完成”);
});
};
这实际上是一个非常简单的解决方案,我一定忽略了。特定道具组件中的类型是错误的
而不是:
requestAuthenticationAsync: typeof requestAuthenticationAsync;
我把它改成:
requestAuthenticationAsync: ReturnType<requestAuthenticationAsync>;
requestAuthenticationAsync:ReturnType;
这能够捕获(email:string,password:string)=>Promise
类型,编译器停止抱怨,一切正常
requestAuthenticationAsync: ReturnType<requestAuthenticationAsync>;