1 | import React from 'react'
|
2 |
|
3 |
|
4 | import { store } from '../'
|
5 | import hoistStatics from 'hoist-non-react-statics'
|
6 |
|
7 | let currentMetaTags
|
8 | let everMounted = false
|
9 | let nodeCommentEnd
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | export default (funcGetPageInfo) => (WrappedComponent) => {
|
23 | const getInfo = (store, renderProps) => {
|
24 | if (typeof funcGetPageInfo !== 'function') return
|
25 |
|
26 | const state = store.getState()
|
27 | let infos = funcGetPageInfo(state, renderProps)
|
28 | if (typeof infos !== 'object') infos = {}
|
29 |
|
30 | const {
|
31 | title = '',
|
32 | metas = []
|
33 | } = infos
|
34 |
|
35 | if (state.localeId) {
|
36 | if (!metas.some(meta => {
|
37 | if (meta.name === 'koot-locale-id') {
|
38 | meta.content = state.localeId
|
39 | return true
|
40 | }
|
41 | return false
|
42 | })) {
|
43 | metas.push({
|
44 | name: 'koot-locale-id',
|
45 | content: state.localeId
|
46 | })
|
47 | }
|
48 | }
|
49 |
|
50 | return {
|
51 | title,
|
52 | metas
|
53 | }
|
54 | }
|
55 |
|
56 | class KootPage extends React.Component {
|
57 |
|
58 |
|
59 |
|
60 | static onServerRenderHtmlExtend = ({ htmlTool, store, renderProps = {} }) => {
|
61 | const infos = getInfo(store, renderProps)
|
62 | htmlTool.title = infos.title
|
63 | htmlTool.metas = infos.metas
|
64 | }
|
65 |
|
66 | updateInfo() {
|
67 | if (__SERVER__) return
|
68 |
|
69 | const infos = getInfo(store, this.props)
|
70 |
|
71 |
|
72 | document.title = infos.title
|
73 |
|
74 |
|
75 | const head = document.getElementsByTagName('head')[0]
|
76 | if (!Array.isArray(currentMetaTags)) {
|
77 | currentMetaTags = []
|
78 |
|
79 |
|
80 | const childNodes = head.childNodes
|
81 | const nodesToRemove = []
|
82 | let meetStart = false
|
83 | let meetEnd = false
|
84 | let i = 0
|
85 | while (!meetEnd && childNodes[i] instanceof Node) {
|
86 | const node = childNodes[i]
|
87 | if (node.nodeType === Node.COMMENT_NODE) {
|
88 | if (node.nodeValue === __KOOT_INJECT_METAS_START__)
|
89 | meetStart = true
|
90 | if (node.nodeValue === __KOOT_INJECT_METAS_END__) {
|
91 | meetEnd = true
|
92 | nodeCommentEnd = node
|
93 | }
|
94 | } else if (meetStart && node.nodeType === Node.ELEMENT_NODE && node.tagName === 'META') {
|
95 | nodesToRemove.push(node)
|
96 | }
|
97 | i++
|
98 | }
|
99 | nodesToRemove.forEach(el => head.removeChild(el))
|
100 | }
|
101 |
|
102 | currentMetaTags.forEach(el => {
|
103 | if (el && el.parentNode)
|
104 | el.parentNode.removeChild(el)
|
105 | })
|
106 | currentMetaTags = infos.metas
|
107 | .filter(meta => typeof meta === 'object')
|
108 | .map(meta => {
|
109 | const el = document.createElement('meta')
|
110 | for (var key in meta) {
|
111 | el.setAttribute(key, meta[key])
|
112 | }
|
113 |
|
114 | if (nodeCommentEnd) {
|
115 | head.insertBefore(el, nodeCommentEnd)
|
116 | } else {
|
117 | head.appendChild(el)
|
118 | }
|
119 | return el
|
120 | })
|
121 | }
|
122 |
|
123 | componentDidUpdate(prevProps) {
|
124 | if (typeof prevProps.location === 'object' &&
|
125 | typeof this.props.location === 'object' &&
|
126 | prevProps.location.pathname !== this.props.location.pathname
|
127 | )
|
128 | this.updateInfo()
|
129 | }
|
130 |
|
131 | componentDidMount() {
|
132 | if (!everMounted) {
|
133 | everMounted = true
|
134 | return
|
135 | }
|
136 | this.updateInfo()
|
137 | }
|
138 |
|
139 | render = () => <WrappedComponent {...this.props} />
|
140 | }
|
141 |
|
142 | return hoistStatics(KootPage, WrappedComponent)
|
143 | }
|
144 |
|
\ | No newline at end of file |