我正在尝试从基于类的组件迁移到功能组件。它是使用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();
}
}, []);
那么,既然articles
和fetchArticles
不像this.props.articles
那样被称为,只有这样articles
,那么props
将如何工作,在mapState
上传播道具…props
有什么意义吗?
没有必要在mapState
中传播道具。
这:
const mapState = (state: AppState, props: Props) => ({
articles: state.articleReducers.articles,
...props,
});
相当于这个:
const mapState = (state: AppState) => ({
articles: state.articleReducers.articles,
});
除了来自mapState
和mapDispatch
的 props(您称之为actionCreators
)之外,任何额外的 props 都会传递到您的组件中。
您的代码是可编译的,但使用函数签名并不完全正确connect
。让我们看看签名
<TStateProps = {}, TDispatchProps = {}, TOwnProps = {}, State = {}>(
mapStateToProps: MapStateToPropsParam<TStateProps, TOwnProps, State>,
mapDispatchToProps: MapDispatchToPropsNonObject<TDispatchProps, TOwnProps>
): InferableComponentEnhancerWithProps<TStateProps & TDispatchProps, TOwnProps>;
它有4种类型,
TSTateProps
是道具的类型,派生自 Redux 状态。在您的样本中,它们是type StateProps = { articles: Article[]; }
只有
articles
是从 Redux 状态派生的。TDispatchProps
是包含组件将调度的操作的道具类型。当你actionCreators
对象传递给connect
TDispatchProps
应该等于typeof actionCreators
(我们应该得到对象类型actionCreators
)。TOwnProps
是你的组件从父级(而不是从 Redux)获得的道具类型。您不使用父级的道具,因此TOwnProps
等于{}
。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;
您的代码在向mapState
添加...props
时工作。props
包含成员fetchAction
.所以你终于得到了与我在答案中显示的相同的Props
,但略有错误。