Как правильно использовать «подключение» в реакции-редуксе с помощью Typescript

Я использую машинописный текст в приложении, но обнаружил проблему с реакцией-редукцией. Метод «подключиться» сообщает о проблеме, и я понятия не имею об этом, так как я новичок с машинописным текстом и редуксом. Что мне делать или где в моем коде нужно изменить? Большое спасибо

Приложение, созданное с помощью [email protected], [email protected], [email protected].

// article
interface IArticle {
  title: string,
  author: string
}

// state
interface MyState {
  list: [],
  article: IArticle
}

// stateMapToProps
interface MyStateProps {
  article: IArticle
}

// router match
interface MatchParams {
  id: string
}

// own props
interface MyOwnProps extends RouteComponentProps < MatchParams > {
  article: IArticle,
  dispatch: (o: object) => {}
}

class ArticleContainer extends Component < MyOwnProps, {} > {
  constructor(props: MyOwnProps) {
    super(props);
  }

  componentDidMount() {
    const {
      dispatch
    } = this.props;
    const id = this.props.match.params.id
    dispatch(fetchArticle(id))
  }

  render() {
    const {
      article
    } = this.props;
    return ( <
      Article article = {
        article
      } > < /Article>
    )
  }
}

const mapStateToProps = (state: MyState): MyStateProps => {
  return {
    article: state.article
  }
}

export default connect < MyStateProps, {}, {
  article: IArticle
} > (
  mapStateToProps
)(ArticleContainer)

Вот код асинхронного действия fetchArticle

function fetchArticle(id: string) {
  return function(dispatch: (action: AnyAction) => {}): Promise<void> {
    dispatch(getArticle(id))

    return axios.get(`/article/${id}`)
      .then(res => {
        dispatch(getArticleSuccess(res.data))
      })
  }
}

Ошибка происходит в строке export, и сообщение выглядит следующим образом:

Argument of type '(state: MyState) => MyStateProps' is not assignable to parameter of type 'MapStateToPropsParam'. Type '(state: MyState) => MyStateProps' is not assignable to type 'MapStateToPropsFactory'. Types of parameters 'state' and 'initialState' are incompatible. Type '{}' is missing the following properties from type 'MyState': list, articlets(2345)

Просто удалите ввод из подключения. Connect уже делает вывод из mapStateToProps. export default connect(mapStateToProps)(ArticleContainer);

eenagy 10.07.2019 07:44

также ваш компонент должен быть Component<MyOwnProps, MyState>

eenagy 10.07.2019 07:45

рекомендуем проверить следующие ресурс

eenagy 10.07.2019 07:46

@eenagy сначала спасибо. Я попробовал, и вместо этого часть ArticleContainer в строке export сообщает о сообщении, а также interface MyState представляет собой структуру хранилища, созданного с помощью избыточности, а не «состояние» Class, поэтому я думаю, что нет необходимости помещать его в дженерики. Надеюсь, я выражаюсь понятно.

smilebuz 10.07.2019 08:00

И сообщение об ошибке для ArticleContainer в части connect выглядит следующим образом (запишите только первое предложение, так как оно слишком длинное, чтобы писать здесь): Аргумент типа 'typeof ArticleContainer' не может быть назначен параметру типа 'ComponentType<Matching<MyStateProps & DispatchProp <AnyAction>, MyOwnProps>>'......ts(2345)

smilebuz 10.07.2019 08:01
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
5
2 146
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вот рабочий пример того, как ввести файл реакции при использовании избыточности на основе вашего примера.

// article-container.js file
import { connect, DispatchProp } from "react-redux";
import { Component } from "react";

// import the real RouteComponent, this is just a demo example
interface RouteComponentProps<T> {
  match: { params: T };
}
// article
interface IArticle {
  title: string;
  author: string;
}
// import the real Article, this is just a demo example

const Article = ({ article }: { article: IArticle }) => {
  return <div>{article.title}</div>;
};

// import the real fetchArticle, this is just a demo example

const fetchArticle = (id: string) => {
  return {
    type: "SOME_ACTION",
    payload: {
      id,
    },
  };
};

// state
interface MyState {
  list: [];
  article: IArticle;
}

// stateMapToProps
interface MyStateProps {
  article: IArticle;
}

// router match
interface MatchParams {
  id: string;
}

// own props
interface MyOwnProps {
  article: IArticle;
}
type AllProps = MyOwnProps & RouteComponentProps<MatchParams> & DispatchProp;

class ArticleContainer extends Component<AllProps> {
  constructor(props: AllProps) {
    super(props);
  }

  componentDidMount() {
    const { dispatch } = this.props;
    const id = this.props.match.params.id;
    dispatch(fetchArticle(id));
  }

  render() {
    const { article } = this.props;
    return <Article article = {article} />;
  }
}

const mapStateToProps = (state: MyState): MyStateProps => {
  return {
    article: state.article,
  };
};

export default connect(
  mapStateToProps
)(ArticleContainer);

И использовать его так


import ArticleContainer from "./article-container";

export default () => {
  // this is coming from router, just an example for demonstration
  const match = { params: { id: "23" } };
  return (
    <div>
      <ArticleContainer match = {match} />
    </div>
  );
};

Спасибо за вашу помощь, я решил проблему, основанную на этом.

smilebuz 10.07.2019 09:46
Ответ принят как подходящий

Минимальные шаги для компиляции кода:

  1. MyOwnProps должно быть

    import { AnyAction } from 'redux';
    
    interface AppThunkAction<TAction> {
        (dispatch: (action: TAction) => void, getState: () => MyState): any;
    }
    
    // As you're going to dispatch thunk actions, dispatch should be overloaded
    interface Dispatch<TAction> {
        (action: AppThunkAction<TAction>): any
        (action: TAction): TAction
    }
    
    // own props
    interface MyOwnProps extends RouteComponentProps<MatchParams> {
        article: IArticle,
        dispatch: Dispatch<AnyAction>
    }
    
  2. Если вы хотите указать типы для функции connect, добавьте MyState в качестве последнего типа, например:

    export default connect <MyStateProps, {}, {
            article: IArticle
        }, MyState >(
            mapStateToProps
    )(ArticleContainer)
    

    Или вы можете позволить компилятору самому выводить типы, что предпочтительнее

    export default connect(
        mapStateToProps
    )(ArticleContainer)
    

Итак, рабочий результат

import { Component } from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { connect, ResolveThunks } from 'react-redux';
import { AnyAction } from 'redux';
import axios from 'axios';

// article
interface IArticle {
    title: string,
    author: string
}

// state
interface MyState {
    list: [],
    article: IArticle
}

// stateMapToProps
interface MyStateProps {
    article: IArticle
}

// router match
interface MatchParams {
    id: string
}

export interface AppThunkAction<TAction> {
    (dispatch: (action: TAction) => void, getState: () => MyState): any;
}

interface Dispatch<TAction> {
    (action: AppThunkAction<TAction>): any
    (action: TAction): TAction
}

// own props
interface MyOwnProps extends RouteComponentProps<MatchParams> {
    article: IArticle,
    dispatch: Dispatch<AnyAction>
}

function getArticle(id: string) {
    return {
        type: 'GET_ARTICLE',
        id
    }
}

function getArticleSuccess(i: any) {
    return {
        type: 'SET_ARTICLE',
        i
    }
}



const fetchArticle = (id: string): AppThunkAction<AnyAction> =>
    (dispatch, getState) => {
        dispatch(getArticle(id))

        return axios.get(`/article/${id}`)
            .then(res => {
                dispatch(getArticleSuccess(res.data))
            })
    }

class ArticleContainer extends Component<MyOwnProps, {}> {
    constructor(props: MyOwnProps) {
        super(props);
    }

    componentDidMount() {
        const {
            dispatch
        } = this.props;
        const id = this.props.match.params.id
        dispatch(fetchArticle(id))
    }

    render() {
        const {
            article
        } = this.props;
        return (<div>article: {article}</div>
          )
        }
      }

const mapStateToProps = (state: MyState): MyStateProps => {
  return {
                article: state.article
          }
        }

export default connect(
            mapStateToProps
)(ArticleContainer)

Спасибо за вашу помощь. Этот метод решает упомянутую мной ошибку, однако dispatch(fetchArticle(id)) сообщает об ошибке, потому что мой fetchArticle метод является асинхронным и возвращает обещание? ps: дополняю код fetchArticle в вопросе.

smilebuz 10.07.2019 09:10

Я думаю, что ошибка в основном сообщает о типе параметра, но я понятия не имею, как ее решить. Вот сообщение об ошибке: Аргумент типа '(dispatch: (action: AnyAction) => {}) => Promise<void>' не может быть назначен параметру типа 'AnyAction'. Свойство 'type' отсутствует в типе '(dispatch: (action: AnyAction) => {}) => Promise<void>', но требуется в типе 'AnyAction'.ts(2345)

smilebuz 10.07.2019 09:16

Я уже решил проблему на основе вашего метода, большое спасибо за вашу помощь!

smilebuz 10.07.2019 09:47

Извините, не упоминает об этом. Я обновил ответ и набрал dispatch, чтобы он мог принимать функции в качестве аргументов.

Fyodor 10.07.2019 09:53

Наконец, решено с удалением объявления дженериков метода connect и использованием ThunkDispatch с создателем асинхронного действия. Код ниже.

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { ThunkDispatch } from 'redux-thunk';
import { fetchArticle } from '../store/actions';
import { RouteComponentProps } from 'react-router-dom';
import Article from '../components/Article/Article'
import { AnyAction } from 'redux';

// article
interface IArticle {
  title: string,
  author: string
}

// state
interface MyState {
  list: [],
  article: IArticle
}

// stateMapToProps
interface StateToProps {
  article: IArticle
}

// router match
interface MatchParams {
  id: string
}

// own props
interface MyOwnProps extends RouteComponentProps<MatchParams> {
  article: IArticle,
  getArticle: (id: string) => Promise<void>
}

class ArticleContainer extends Component<MyOwnProps, {}> {
  constructor(props: MyOwnProps) {
    super(props);
  }

  componentDidMount() {
    const { getArticle } = this.props;
    const id = this.props.match.params.id
    getArticle(id)
  }

  render() {
    const { article } = this.props;
    return (
      <Article article = {article}></Article>
    )
  }
}

const mapStateToProps = (state: MyState): StateToProps => {
  return {
    article: state.article
  }
}

const mapDispatchToProps = (dispatch: ThunkDispatch<any, any, AnyAction>) => {
  return {
    getArticle: (id: string) => dispatch(fetchArticle(id))
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(ArticleContainer)

Спасибо за помощь!

Другие вопросы по теме