【问题标题】:How can I properly migrate a connected component from class based to functional component on TS?如何正确地将连接的组件从基于类的组件迁移到 TS 上的功能组件?
【发布时间】:2019-11-21 18:14:53
【问题描述】:

我正在尝试从基于类的组件迁移到功能组件。它是一个使用mapState 的连接组件。

这就是我所拥有的:

import { connect } from 'react-redux'
import { fetchArticles } from '../shared/actions/articleActions';
import { AppState } from '../shared/types/genericTypes';
import Article from '../shared/models/Article.model';

type Props = {
  articles?: Article[]
  fetchArticles?: any,
};

const mapState = (state: AppState, props) => ({
  articles: state.articleReducers.articles,
  ...props
});

const actionCreators = {
  fetchArticles,
};

class NewsArticles extends Component<Props> {
  componentDidMount() {
    if (!this.props.articles || !this.props.articles.length) {
      this.props.fetchArticles();
    }
  }

  render() {
    return (...);
  }
}

export default connect(mapState, actionCreators)(NewsArticles)

这是我现在拥有的:

// same imports except for FC and useEffec from react.

type Props = {
  articles?: Article[];
  fetchArticles?: any;
};

const mapState = (state: AppState, props: Props) => ({
  articles: state.articleReducers.articles,
  ...props,
});

const actionCreators = {
  fetchArticles,
};

const NewsArticles: FC<Props> = ({ articles, fetchArticles }) => {
  useEffect(() => {
    if (!articles || !articles.length) {
      fetchArticles();
    }
  }, []);

  return (...);
};

export default connect(mapState, actionCreators)(NewsArticles);

我最关心的是道具。

以前他们是这样的

const mapState = (state: AppState, props) => ({
  articles: state.articleReducers.articles,
  ...props
});

并像这样使用:

 componentDidMount() {
    if (!this.props.articles || !this.props.articles.length) {
      this.props.fetchArticles();
    }
  }

现在我有了一个功能组件,我得到了这个

const mapState = (state: AppState, props: Props) => ({
  articles: state.articleReducers.articles,
  ...props,
});

并像这样使用:

  useEffect(() => {
    if (!articles || !articles.length) {
      fetchArticles();
    }
  }, []);

那么props 将如何工作现在articlesfetchArticles 不像this.props.articles 和只有articles 那样被调用所以,在mapState 上传播道具…props 是否有意义?

【问题讨论】:

  • 是的,您所做的绝对正确,props 中的内容不取决于组件是类还是功能性。它由连接 HOC 提供
  • mapState 调用中的道具当然是组件自己的道具,所以如果你想将它可能收到的任何其他道具分配给它的状态,那么在地图调用中传播它们是有意义的。但是除非你对 props 执行某种操作,而且通常即使你这样做了,从它们派生状态通常是不必要的。因此,无论组件类型如何,它都不是必需的,但它没有真正的缺点。
  • 无需传播propsNewsArticles 需要的所有道具都由connect 提供:articles from state and fetchArticles from actionCreators

标签: javascript reactjs typescript ecmascript-6 redux


【解决方案1】:

mapState 无需传播道具。

这个:

const mapState = (state: AppState, props: Props) => ({
  articles: state.articleReducers.articles,
  ...props,
});

等价于:

const mapState = (state: AppState) => ({
  articles: state.articleReducers.articles,
});

除了来自mapStatemapDispatch(你称之为actionCreators)的道具之外,任何额外的道具都会被传递到你的组件中。

【讨论】:

    【解决方案2】:

    您的代码是可编译的,但与 connect 函数签名不完全正确。让我们看看签名

    <TStateProps = {}, TDispatchProps = {}, TOwnProps = {}, State = {}>(
        mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps, State>,
        mapDispatchToProps: MapDispatchToPropsNonObject<TDispatchProps, TOwnProps>
    ): InferableComponentEnhancerWithProps<TStateProps & TDispatchProps, TOwnProps>;
    

    它有4种类型,

    1. TSTateProps 是 props 的类型,派生自 Redux 状态。在您的示例中,它们是

      type StateProps = {
          articles: Article[];
      }
      

      只有 articles 派生自 Redux 状态。

    2. TDispatchProps 是包含组件将调度的操作的道具类型。当您将actionCreators 对象传递给connect TDispatchProps 时,应该等于typeof actionCreators(我们应该得到对象类型actionCreators)。

    3. TOwnProps 是组件从父组件(而不是 Redux)获取的道具类型。你不使用父级的道具,所以TOwnProps 将等于{}

    4. TState 是 Redux 中的状态类型。是AppState

    所以要完全正确地使用 Redux,你应该这样做

    type StateProps = {
        articles: Article[];
    };
    
    const mapState = (state: AppState): StateProps => ({
        articles: state.articleReducers.articles
    });
    
    const actionCreators = {
        fetchArticles,
    };
    
    type Props = StateProps & typeof actionCreators;  // These is correct props for your component
    
    const NewsArticles: FC<Props> = ({ articles, fetchArticles }) => {
    

    如果您稍后会从父级添加道具,只需将它们与Props 相交即可。

    type Props = StateProps & typeof actionCreators & OwnProps;
    

    您的代码在您将...props 添加到mapState 时有效。而props 包含成员fetchAction。因此,您最终得到了与我在答案中显示的相同的Props,但略有错误。

    【讨论】:

      猜你喜欢
      • 2020-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-27
      • 2020-09-27
      • 2020-09-28
      相关资源
      最近更新 更多