Reduxとreact-router-domを使用して、TypeScriptで反応アプリを構築しようとしています。アプリにreduxを追加すると、タイピングの問題が発生しました。したがって、1ページのみtest-pageで次の最小限の例を作成しました。
App.jsx
import * as React from 'react';
import { Route, Redirect } from 'react-router-dom'
import Test from './containers/test-page'
import './App.css';
class App extends React.Component {
render() {
return (
<div className="ui container" id="main">
<Route exact path="/" render={() => <Redirect to="/test" />}/>
<Route exact path="/test" component={Test} />
</div>
);
}
}
export default App;
テストページのコンテナは次のようになります。 connectへの呼び出しで入力エラーが発生します。
コンテナ/テストページ/index.tsx
import { Dispatch } from 'redux'
import { connect } from 'react-redux'
import TestPage from './test-page'
function mapDispatchToProps(dispatch: Dispatch<any>) {
return dispatch({ type: 'ALERT_USER' });
}
function mapStateToProps(state: any) {
return { label: 'my test label' }
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(TestPage)
コンテナは次の反応コンポーネントを使用します。これは、実稼働環境ではルーターのページをレンダリングする必要があります。以下の2つのエラーが発生します。
コンテナ/テストページ/テストページ.tsx
import * as React from 'react';
export namespace Test {
export interface Props {
alert: () => void;
label: string;
}
export interface State {
}
}
export default class TestPage extends React.Component {
constructor(props?: Test.Props, state?: Test.State, context?: any) {
super(props, context);
}
sendAlert = () => {
this.props.alert()
}
render() {
return (
<div>
<h1>Test</h1>
<button onClick={this.sendAlert}>{this.props.label}</button>
</div>
);
}
}
proxyConsole.js:54 ./src/containers/test-page/test-page.tsx
(20,18): error TS2339: Property 'alert' does not exist on type 'Readonly<{ children?: ReactNode; }> & Readonly<{}>'.
proxyConsole.js:54 ./src/containers/test-page/test-page.tsx
(27,54): error TS2339: Property 'label' does not exist on type 'Readonly<{ children?: ReactNode; }> & Readonly<{}>'.
proxyConsole.js:54 ./src/containers/test-page/index.tsx
(16,3): error TS2345: Argument of type 'typeof TestPage' is not assignable to parameter of type 'ComponentType<{ label: string; } & { type: string; }>'.
Type 'typeof TestPage' is not assignable to type 'StatelessComponent<{ label: string; } & { type: string; }>'.
Type 'typeof TestPage' provides no match for the signature '(props: { label: string; } & { type: string; } & { children?: ReactNode; }, context?: any): ReactElement<any> | null'.
さまざまなガイドに従い、実装例を調べましたが、これらの問題を解決できませんでした。 TypeScriptコンパイラのエラーメッセージがわかりません。
this.props
にプロパティが存在しないのはなぜですか?私が気づくいくつかのこと:
1)例で見た限り、およびTypeScriptでprops
を使用する場合、React.Component
を呼び出すには、Props
を次のように型引数として指定する必要があります。
export default class TestPage extends React.Component<Test.Props, Test.State>{
constructor(props: Test.Props) {
super(props);
}
}
空のインターフェースを渡すことにより、コンポーネントがprops
またはstate
を受け入れないように指定できます:
export default class TestPage extends React.Component<{}, {}>{
// constructor becomes 'useless' at this point and is not needed
constructor() {
super();
}
}
これは、コールシグネチャが一致しない理由と、this.props
に表示されるプロパティがない理由を説明していると思います。TSには、型引数が渡されないため、ReadOnly{}
のインターフェイスが表示されます。
2)mapStateToProps
関数が正しく見えません。 mapStateToProps
は、state
(Redux store
を参照)と、オプションの2番目の引数としてownProps
の2つの引数を取ります。これは、親から渡されたprops
を参照します。したがって、mapStateToProps
は次のようになります。
function mapStateToProps(state: any, ownProps: { label: string }) {
return {
label: ownProps.label
};
}
これは、connect
がエラーをスローしている理由の推測です。単に、props
からのstore
と親からのprops
を組み合わせてReduxがどのように処理するかについてアサーションを行う場所です。これがうまくいくかどうか教えてください。
Connectは汎用関数であるため、これは機能しません。これは、追加の型パラメーターを提供する必要があることを意味します。
connect<StateProps, DispatchProps>({
mapStateToProps,
mapDispatchToProps,
})(SomeComponent);
タイピングの実装を見つけることができます こちら 。知っておくべきことはすべてありますC:
タイプスクリプトアプリケーションの動作構文バリアントは次のとおりです。
import * as React from 'react';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';
class MyComponentName extends React.Component<any, any> {
constructor(props: any) {
super(props);
}
}
export default withRouter(
connect(
mapStateToProps
)(MyComponentName) as any
);
または:
export default withRouter(
connect<any, any>(
mapStateToProps
)(MyComponentName) as any
);