我应该使用 ComponentDidMount 还是 connect 函数的 mergeProps 来获取数据?
Should I use ComponentDidMount or mergeProps of connect function for data fetching?
我使用 react with redux 并有一个组件显示从外部源获取的一些数据集。我当前的代码如下:
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[ 中加载它会更好吗? =26=]函数?代码可能如下所示:
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 进行异步抓取。
第二种方法,作为概念分离,可能是一个很好的解决方案,因为层和职责分离 - ConnectedComponent
负责数据获取,而MyComponent
充当演示组件。好!
但是,在连接 mergeProps
中调度操作似乎不是一个好主意,因为你引入了 副作用。
另外,我看到的另一个缺点是,获取和返回数据的流程将在不同的页面(组件)之间重复。一般来说,会重复以下流程:
- 已连接的组件为所需的实体调用 API。
- 在获取实体时,我们正在显示加载程序。
- 当数据可用时,我们将其传递给演示组件。
由于上述缺点,我建议您在 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 课:增强型容器
我使用 react with redux 并有一个组件显示从外部源获取的一些数据集。我当前的代码如下:
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[ 中加载它会更好吗? =26=]函数?代码可能如下所示:
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 进行异步抓取。
第二种方法,作为概念分离,可能是一个很好的解决方案,因为层和职责分离 - ConnectedComponent
负责数据获取,而MyComponent
充当演示组件。好!
但是,在连接 mergeProps
中调度操作似乎不是一个好主意,因为你引入了 副作用。
另外,我看到的另一个缺点是,获取和返回数据的流程将在不同的页面(组件)之间重复。一般来说,会重复以下流程:
- 已连接的组件为所需的实体调用 API。
- 在获取实体时,我们正在显示加载程序。
- 当数据可用时,我们将其传递给演示组件。
由于上述缺点,我建议您在 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 课:增强型容器