it-roy-ru.com

Использовать реакцию-редукса в машинописи

Я пытаюсь создать реагирующее приложение в TypeScript, используя redux и Reaction-router-dom. Я столкнулся с проблемами при наборе текста, когда я добавил избыточность в свое приложение. Таким образом, я создал следующий минимальный пример только с одной страницей 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)

Контейнер использует следующий компонент реагирования, который при производстве должен отобразить страницу для маршрутизатора. Выдает две ошибки, см. Ниже.

контейнеры/тест-страница/тест-page.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, когда я их определил?
  • Что именно не присваивается в коннекте?
2
Simon

Я заметил пару вещей:

1) Насколько я видел в примерах и при работе с props в TypeScript, ваш вызов 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) и ownProps в качестве необязательного второго аргумента, который ссылается на props, передаваемый от родителя. Итак, mapStateToProps должен выглядеть так:

function mapStateToProps(state: any, ownProps: { label: string }) {

    return {
        label: ownProps.label
    };
}

Это мое предположение о том, почему connect генерирует ошибку - это просто место, где вы делаете утверждения о том, как Redux должен обрабатывать комбинирование props из store и props из родительского объекта. Дайте мне знать, если это сработает.

9
Parker Ziegler

Это не работает, потому что connect является универсальной функцией. Это означает, что вам нужно предоставить дополнительные параметры типа.

connect<StateProps, DispatchProps>({
    mapStateToProps,
    mapDispatchToProps,
})(SomeComponent);

Вы можете найти реализацию ввода здесь . Все, что вам нужно знать, есть C:

8
Kacper Wiszczuk

Вариант рабочего синтаксиса для приложения Type Script:

  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
  );
0
Jackkobec