由于 ReactJS 虚拟 DOM 非常快,我假设最大的加载时间是由于异步调用。您可能在 React 生命周期事件之一中运行异步代码(例如 componentWillMount)。
在 HTTP 调用所需的时间内,您的应用程序看起来是空的。要创建加载器,您需要保持异步代码的状态。
不使用 Redux 的示例
我们的应用程序将具有三种不同的状态:
- REQUEST:请求数据但尚未加载。
- SUCCESS:数据返回成功。没有发生错误。
- FAILURE:异步代码因错误而失败。
当我们处于请求状态时,我们需要渲染微调器。一旦数据从服务器返回,我们将应用程序的状态更改为SUCCESS,这会触发组件重新渲染,我们会在其中渲染列表。
import React from 'react'
import axios from 'axios'
const REQUEST = 'REQUEST'
const SUCCESS = 'SUCCESS'
const FAILURE = 'FAILURE'
export default class Listings extends React.Component {
constructor(props) {
super(props)
this.state = {status: REQUEST, listings: []}
}
componentDidMount() {
axios.get('/api/listing/12345')
.then(function (response) {
this.setState({listing: response.payload, status: SUCCESS})
})
.catch(function (error) {
this.setState({listing: [], status: FAILURE})
})
}
renderSpinner() {
return ('Loading...')
}
renderListing(listing, idx) {
return (
<div key={idx}>
{listing.name}
</div>
)
}
renderListings() {
return this.state.listing.map(this.renderListing)
}
render() {
return this.state.status == REQUEST ? this.renderSpinner() : this.renderListings()
}
}
使用 Redux 的示例
你几乎可以使用 Redux 和 Thunk 中间件来做类似的事情。
Thunk 中间件允许我们发送作为函数的操作。因此,它允许我们运行异步代码。在这里,我们正在做与上一个示例相同的事情:我们跟踪异步代码的状态。
export default function promiseMiddleware() {
return (next) => (action) => {
const {promise, type, ...rest} = action
if (!promise) return next(action)
const REQUEST = type + '_REQUEST'
const SUCCESS = type + '_SUCCESS'
const FAILURE = type + '_FAILURE'
next({...rest, type: REQUEST})
return promise
.then(result => {
next({...rest, result, type: SUCCESS})
return true
})
.catch(error => {
if (DEBUG) {
console.error(error)
console.log(error.stack)
}
next({...rest, error, type: FAILURE})
return false
})
}
}