Component
を使用しconnect
、カスタム プロパティを受け取るReact がありますwithRouter
。これを TypeScript に変換しようとしていますが、正しく実行できているかどうか疑問に思っています。少なくとも、今のところエラーはありません。
これは概念を示すコードです:
import * as React from 'react'
import { connect } from 'react-redux';
import { withRouter, RouteComponentProps } from 'react-router';
import {
fetchTestLists,
newTestList,
displayTestList,
} from '../../../actions/index';
interface StateProps {
testList: any; // todo: use the type of state.myList to have validation on it
}
interface DispatchProps {
fetchTestLists: () => void;
newTestList: () => void;
displayTestList: (any) => void; // todo: replace any with the actual type
}
interface Props { // custom properties passed to component
className: string;
}
type PropsType = StateProps & DispatchProps & Props;
class MyTest extends React.Component<PropsType & RouteComponentProps<{}>, {}> {
constructor(props) {
super(props);
this.handleCellClick = this.handleCellClick.bind(this);
this.newTestList = this.newTestList.bind(this);
}
componentDidMount() {
this.props.fetchTestLists();
}
handleCellClick(row, column, event) {
this.props.displayTestList(row);
}
newTestList(e) {
this.props.newTestList()
}
render() {
return (
<div className={this.props.className}>
</div>
);
}
}
const mapStateToProps = (state): StateProps => ({
testList: state.myList, // todo: define a type for the root state to have validation here
});
const dispatchToProps = {
fetchTestLists,
newTestList,
displayTestList,
};
export default withRouter<Props & RouteComponentProps<{}>>(connect<StateProps, DispatchProps>(
mapStateToProps,
dispatchToProps,
)(MyTest) as any);
コンポーネントは次のように使用されます。<MyTest className={"active"} />
これを機能させるには、多くの実験が必要でした。たとえば、次のようになります。
1) 次のように withRouter の型を省略すると、次のようにexport default withRouter(connect...
なります。TS2339: Property 'className' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<Pick<RouteComponentProps<any>, never>, C...'.
これは何らかの形でここで提案されています。TypeScript の React ルーター - ルーターと独自のプロパティの両方ただし、私はその概念を理解していません。
2) 最後の行について疑問に思うかもしれませんがas any
、これはhttps://github.com/DefinitelyTyped/DefinitelyTyped/issues/18999それがないと、次のエラーが発生します:
TS2345: Argument of type 'ComponentClass<Pick<any, never>> & { WrappedComponent: ComponentType<any>; }' is not assignable to parameter of type 'ComponentType<Props & RouteComponentProps<{}>>'.
Type 'ComponentClass<Pick<any, never>> & { WrappedComponent: ComponentType<any>; }' is not assignable to type 'StatelessComponent<Props & RouteComponentProps<{}>>'.
Type 'ComponentClass<Pick<any, never>> & { WrappedComponent: ComponentType<any>; }' provides no match for the signature '(props: Props & RouteComponentProps<{}> & { children?: ReactNode; }, context?: any): ReactElement<any> | null'.
それで、これは正しいやり方ですか? どこに問題があると思いますか? 私は基本的に最新バージョンをすべて使用しています。以下は私の package.json からの抜粋です:
"react": "^16.2.0",
"redux": "^3.7.2",
"react-dom": "^16.2.0",
"react-redux": "^5.0.6",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-router-redux": "^4.0.8",
...
"typescript": "^2.7.2",
"@types/react-redux": "^5.0.15",
"@types/react-router": "^4.0.22",
"@types/react-router-dom": "^4.2.4",
"@types/react": "^16.0.38",
"@types/react-dom": "^16.0.4",
ベストアンサー1
私たちのプロジェクトでそれを実行する方法 (これが最も簡単な方法であり、これを使用するとインテリセンスを利用できます):
import * as React from 'react'
import { connect } from 'react-redux';
import { withRouter, RouteComponentProps } from 'react-router';
import {
fetchTestLists,
newTestList,
displayTestList,
} from '../../../actions/index';
interface StateProps {
testList: any; // todo: use the type of state.myList to have validation on it
}
interface DispatchProps {
fetchTestLists: () => void;
newTestList: () => void;
displayTestList: (any) => void; // todo: replace any with the actual type
}
interface Props extends RouteComponentProps { // custom properties passed to component
className: string;
}
type PropsType = StateProps & DispatchProps & Props;
class MyTest extends React.Component<PropsType> {
constructor(props) {
super(props);
this.handleCellClick = this.handleCellClick.bind(this);
this.newTestList = this.newTestList.bind(this);
}
componentDidMount() {
this.props.fetchTestLists();
}
handleCellClick(row, column, event) {
this.props.displayTestList(row);
}
newTestList(e) {
this.props.newTestList()
}
render() {
return (
<div className={this.props.className}>
</div>
);
}
}
const mapStateToProps = (state, ownProps: Props): StateProps => ({
testList: state.myList, // todo: define a type for the root state to have validation here
});
const dispatchToProps: DispatchProps = {
fetchTestLists,
newTestList,
displayTestList,
};
export default withRouter(connect(
mapStateToProps,
dispatchToProps,
)(MyTest));
また、これを頻繁に入力する場合は、カスタム スニペットを作成することをお勧めします (VS Code などを使用している場合は非常に簡単です)。