UNPKG

3.02 kBJavaScriptView Raw
1import React from 'react'
2import hoistStatics from 'hoist-non-react-statics'
3import { store } from '../index.js'
4
5/**
6 * 获取数据
7 * @callback funcFetchData
8 * @param {Object} state 当前 state
9 * @param {Object} renderProps 服务器端渲染时的 props
10 * @param {Function} dispatch Redux dispatch 方法
11 * @returns {Promise}
12 */
13
14/**
15 * 判断数据是否准备好
16 * @callback callbackCheckLoaded
17 * @param {Object} state 当前 state
18 * @param {Object} ownProps 当前组件的 props 对象
19 * @returns {Boolean}
20 */
21
22/**
23 * 数据载入时渲染的内容
24 * @callback callbackLoader
25 * @param {Object} state 当前 state
26 * @param {Object} ownProps 当前组件的 props 对象
27 * @returns {String}
28 */
29
30/**
31 * 负责数据同构的组件装饰器
32 * @param {funcFetchData} callback 方法: 获取数据,需要返回 Promise。如果提供了 checkLoaded() 方法,组件中会获得 props.loaded 属性,表示数据是否读取完毕
33 * @param {Object} [options={}] 选项
34 * @param {callbackCheckLoaded} [options.checkLoaded] 方法:判断数据是否准备好。需要返回 Boolean
35 * @param {callbackLoader|String} [options.loader] 数据载入时渲染的内容。如果提供,在载入数据时会渲染该内容。
36 */
37
38export default (funcFetchData, options = {}) => (WrappedComponent) => {
39
40 const {
41 checkLoaded,
42 loader
43 } = options
44
45 class KootLoad extends React.Component {
46 // mounted = false
47
48 state = {
49 loaded: typeof checkLoaded === 'function'
50 ? checkLoaded(store.getState(), this.props, store.dispatch)
51 : undefined,
52 }
53
54 static onServerRenderStoreExtend({ store, renderProps }) {
55 if (typeof funcFetchData !== 'function')
56 return new Promise(resolve => resolve())
57 // console.log('onServerRenderStoreExtend')
58 return funcFetchData(store.getState(), renderProps, store.dispatch)
59 }
60
61 componentDidMount() {
62 this.mounted = true
63
64 if (!this.state.loaded) {
65 // console.log('componentDidMount')
66 funcFetchData(store.getState(), this.props, store.dispatch)
67 .then(() => {
68 if (!this.mounted) return
69 this.setState({
70 loaded: true,
71 })
72 })
73 }
74 }
75
76 componentWillUnmount() {
77 this.mounted = false
78 }
79
80 render = () => {
81 if (!this.state.loaded && typeof loader !== 'undefined') {
82 if (typeof loader === 'function')
83 return loader(store.getState(), this.props)
84 return loader
85 }
86
87 return <WrappedComponent loaded={this.state.loaded} {...this.props} />
88 }
89 }
90
91 return hoistStatics(KootLoad, WrappedComponent)
92
93}
94
\No newline at end of file