我对redux使用react并有一个组件,该组件显示一些从外部源获取的dataSet。我当前的代码如下:
const ConnectedComponent = connect(
state => ({
dataSet: state.dataSet
}),
dispatch => ({
loadData: () => {
...
fetch data and dispatch it to the store
...
}
})
)(MyComponent);
class MyComponent extends Component {
...
componentDidMount() {
const { dataSet, loadData } = this.props;
if (!dataSet) {
loadData();
}
}
...
render () {
const { dataSet } = this.props;
if (dataSet) {
// render grid with data
} else {
// render Loading...
}
}
}
上面的代码有效,但是我想知道摆脱 componentDidMount 并检查数据并从 connect 函数中加载数据会更好吗?该代码可能类似于:
const ConnectedComponent = connect(
state => ({
dataSet: state.dataSet
}),
dispatch => ({
dispatch
}),
(stateProps, dispatchProps) => {
const { dataSet } = stateProps;
const { dispatch } = dispatchProps;
if (!dataSet) {
// fetch data asynchronously and dispatch it to the store
}
return {
...stateProps
};
}
)(MyComponent);
class MyComponent extends Component {
render () {
const { dataSet } = this.props;
if (dataSet) {
// render grid with data
} else {
// render Loading...
}
}
}
由于 MyComponent 变得更简单,后一个代码对我来说更具吸引力。当 componentDidMount 检测到没有准备好显示的数据时,先执行从连接的组件到演示组件的传递,然后再执行的传递没有实现。
这种方法是否有缺点?
PS:我使用redux-thunk进行异步获取。
答案 0 :(得分:2)
第二种方法,如概念分离,由于层和职责分离,可能是一个很好的解决方案-ConnectedComponent
负责数据提取,而MyComponent
充当演示组件。好!
但是,在连接mergeProps
中调度动作似乎不是一个好主意,因为您会引入副作用。
此外,我看到的另一个缺点是,获取和返回数据的流程将在您的不同页面(组件)之间重复。一般来说,将重复以下流程:
由于上述缺点,我建议您在 HOC 中组织和重用数据获取流程。
这是伪代码和流程(摘自我的文章),解决了上述缺点:
* 我过去一年一直在使用它,并继续坚持下去。
Fetcher HOC:
import authorActions from 'actions/author'
const actions = {
'Author': authorActions
}
export default (WrappedComponent, entities) => {
class Fetcher extends React.Component {
// #1. Calls the API for the needed Entities.
componentDidMount () {
this.fetch()
}
fetch () {
const { dispatch } = this.props
entities.forEach(name => dispatch(actions[name].get()))
}
render () {
const { isFetching } = this.props
// #2. While fetching the Entities, we're showing an Loader.
if (isFetching) return <Loader />
return <WrappedComponent {...this.props} />
}
}
const mapStateToProps = state => {
const isFetching = entities
.map(entity => state[entity].isFetching)
.filter(isFetching => isFetching)
return { isFetching: isFetching.length > 0 }
}
return connect(mapStateToProps)(Fetcher)
}
用法:
const MyComponent = ({ authors }) => <AuthorsList authors={authors} />
const mapStateToProps = state => ({
authors: state.authors
})
const Component = connect(mapStateToProps)(MyComponent)
export default Fetcher(Component, ['Author'])
在这里您可以阅读本文并深入了解其思想和概念:
* Fetcher概念在第2课:类固醇容器