reactjs – 使用React和TypeScript时,如何正确键入@connect?
我一直在努力解决这个问题.今天坐下来致力于摆脱任何留下的东西,但没有成功.
import * as React from 'react'; import * as Redux from 'redux'; import { connect } from 'react-redux'; import { ReduxState } from './types'; import { syncItem,displayAlert } from './actionCreators'; import { SyncItemAction,DisplayAlertAction } from './actions'; // Props coming from Redux using `connect` and `mapStateToProps` type AppData = { isSelected: boolean; isInEditMode: boolean; }; // Action creators from `./actionCreators` all wrapped in `dispatch` using `connect` and `mapDispatchToProps` type AppActions = { syncItem: (id: number) => SyncItemAction; displayAlert: (text: string) => DisplayAlertAction; }; // Actual JSX attributes that will be required by the type system. type AppProps = { id: number; name: string; } & Partial<AppData> & Partial<AppActions>; // Making data and actions partial so that using <App /> in JSX doesn't yell. // The component's inner state. type AppState = Partial<{ temp: string; }>; @connect<AppData,AppActions,AppProps>(mapStateToProps,mapDispatchToProps)(App) // Or mapDispatchToPropsAlt export default class App extends React.Component<AppProps,AppState> { constructor(props: AppProps) { super(props); } render() { return ( <div> <h1>Hello,{this.props.name}! (#{this.props.id})</h1> {/* In the below,syncItem should take the new name,a detail… Also ID could be provided in `mapStateToProps` by using `ownProps`! */} Rename: <input value={this.state.temp} onChange={event => this.setState({ temp: event.target.value })} /> <button onClick={_ => this.props.syncItem(this.props.id)}>Sync</button> </div> ); } } function mapStateToProps(state: ReduxState,ownProps?: AppProps): AppData { return { isSelected: ownProps.id === state.selectedId,isInEditMode: state.isInEditMode }; } function mapDispatchToProps(dispatch: Redux.Dispatch<ReduxState>,ownProps?: AppProps): AppActions { return { syncItem: (id: number) => dispatch(syncItem(id)),displayAlert: (text: string) => dispatch(displayAlert(text,ownProps.name)) }; } function mapDispatchToPropsAlt(dispatch: Redux.Dispatch<ReduxState>,ownProps?: AppProps): AppActions { return { syncItem,// Making this `null` because `displayAlert` above changes the signature by hiding the other parametr and taking it from `ownProps` - uncommon! displayAlert: null }; } function Test() { // Only `id` and `name` is correctly required. return <App id={0} name={'test'} />; } 在上面的代码中,我得到以下内容: index.tsx(31,78): error TS2345: Argument of type 'typeof App' is not assignable to parameter of type 'ComponentClass<AppData & AppActions> | StatelessComponent<AppData & AppActions>'. Type 'typeof App' is not assignable to type 'StatelessComponent<AppData & AppActions>'. Type 'typeof App' provides no match for the signature '(props: AppData & AppActions & { children?: ReactNode; },context?: any): ReactElement<any>' 我已经使用了node_modules / @ types中的类型定义来得出我上面提到的内容,同样我已经检查了ComponentClass< T>好像.它建议(在我看来)组件的状态必须是{} |我无法理解为什么会出现这种情况,如果我将上面的代码更改为< AppProps,void>或< AppProps,{}>它不会以任何方式改变第一个错误. 我该怎么办呢? syncItem只是函数syncItem(id:number):SyncItemAction和SyncItemAction是接口SyncItemAction扩展Redux.Action {id:number;与displayAlert类似. 编辑:找到一个related question,但这个也没有回答如何输入状态. 解决方法
这个答案不使用注释(并使用接口而不是类型).基本思想是将Connected组件及其props与底层组件完全分开(明智地说明).
创建一个类ConnectedAppProps,它们是您要向Provider公开的连接组件的属性 interface ConnectedAppProps { id: number; name: string; } 从该界面扩展AppProps interface AppProps extends ConnectedAppProps,AppData,AppActions { } 创建ConnectedComponent const ConnectedApp: React.ComponentClass<ConnectedAppProps> = connect<AppData,AppProps>( mapStateToProps,mapDispatchToProps )( App ) 使用Provider下的连接组件及其ConnectedAppProps <Provider store={store}> <ConnectedApp id={0} name={'test'} /> </Provider> 使用今天点的mapStateToProp和mapDispatchToProps来“丰富”组件AppProps与ConnectedAppProps的组件 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |