1- import React , { Component } from 'react' ;
1+ import React , { Fragment , Component } from 'react' ;
22import { parse } from 'url' ;
33import PropTypes from 'prop-types' ;
44import getNested from 'get-nested' ;
55import site from '../site' ;
6+ import EntityMapper from '../EntityMapper' ;
67
7- const components = new Map ( ) ;
8-
9- export default class DrupalPage extends Component {
10- static propTypes = {
11- url : PropTypes . string . isRequired ,
12- layout : PropTypes . oneOfType ( [
13- PropTypes . func ,
14- PropTypes . string ,
15- ] ) ,
16- mapper : PropTypes . oneOfType ( [
17- PropTypes . shape ( ) ,
18- PropTypes . func ,
19- ] ) . isRequired ,
20- asyncMapper : PropTypes . bool ,
21- layoutProps : PropTypes . shape ( ) ,
22- renderWhileLoadingData : PropTypes . bool ,
23- pageProps : PropTypes . shape ( ) ,
24- } ;
25-
26- static defaultProps = {
27- layout : 'div' ,
28- asyncMapper : false ,
29- layoutProps : { } ,
30- renderWhileLoadingData : false ,
31- pageProps : undefined ,
32- } ;
33-
8+ class DrupalPage extends Component {
349 static contextTypes = {
3510 hnContext : PropTypes . object ,
3611 } ;
3712
38- constructor ( props ) {
39- super ( props ) ;
40-
41- this . state = {
42- ready : false ,
43- loadingData : true ,
44- dataUrl : null ,
45- pageUuid : null ,
46- contentTypeComponentSymbol : null ,
47- } ;
48- }
13+ state = {
14+ ready : false ,
15+ loadingData : true ,
16+ dataUrl : null ,
17+ pageUuid : null ,
18+ } ;
4919
5020 /**
5121 * If this component exists in a tree that is invoked with the waitForHnData function, this function is invoked.
@@ -85,7 +55,7 @@ export default class DrupalPage extends Component {
8555 * @param url
8656 * @param mapper
8757 * @param asyncMapper
88- * @returns {Promise.<{pageUuid: void, contentTypeComponentSymbol: Symbol }> }
58+ * @returns {Promise.<{pageUuid: string }> }
8959 */
9060 static async assureData ( { url, mapper, asyncMapper } ) {
9161 // Get the page. If the page was already fetched before, this should be instant.
@@ -94,40 +64,7 @@ export default class DrupalPage extends Component {
9464 throw Error ( 'An error occurred getting a response from the server.' ) ;
9565 }
9666
97- // This gets the data from the site, based on the uuid.
98- const data = site . getData ( pageUuid ) ;
99-
100- // This should give back a bundle string, that is used in the mapper.
101- const bundle = getNested ( ( ) => `${ data . __hn . entity . type } __${ data . __hn . entity . bundle } ` , '_fallback' ) ;
102-
103- // Get the component that belongs to this content type
104- let contentTypeComponent = typeof mapper === 'function' ? mapper ( data , bundle ) : mapper [ bundle ] ;
105-
106- // If asyncMapper is true, execute the function so it returns a promise.
107- if ( asyncMapper && typeof contentTypeComponent === 'function' ) {
108- contentTypeComponent = contentTypeComponent ( ) ;
109- }
110-
111- // If a promise was returned, resolve it.
112- if ( contentTypeComponent && typeof contentTypeComponent . then !== 'undefined' ) {
113- contentTypeComponent = await contentTypeComponent ;
114- }
115-
116- // Make sure there is a contentComponent.
117- if ( ! contentTypeComponent ) {
118- throw Error ( 'No content type found' ) ;
119- }
120-
121- // If it has a .default (ES6+), use that.
122- if ( contentTypeComponent . default ) {
123- contentTypeComponent = contentTypeComponent . default ;
124- }
125-
126- // Store the contentTypeComponent globally, so it can be rendered sync.
127- const contentTypeComponentSymbol = Symbol . for ( contentTypeComponent ) ;
128- components . set ( contentTypeComponentSymbol , contentTypeComponent ) ;
129-
130- return { pageUuid, contentTypeComponentSymbol } ;
67+ return { pageUuid } ;
13168 }
13269
13370 componentWillUnmount ( ) {
@@ -144,31 +81,26 @@ export default class DrupalPage extends Component {
14481
14582 this . setState ( { loadingData : true } ) ;
14683
147- if ( ! this . props . renderWhileLoadingData ) {
148- // Mark this component as not-ready. This unmounts the Layout and old ContentType.
149- this . setState ( { ready : false } ) ;
150- }
151-
15284 // Load the data.
153- const { pageUuid, contentTypeComponentSymbol } = await DrupalPage . assureData ( { url, mapper, asyncMapper} ) ;
85+ const { pageUuid } = await DrupalPage . assureData ( { url, mapper, asyncMapper} ) ;
15486
15587 // Check if this is still the last request.
15688 if ( this . lastRequest !== lastRequest ) return ;
15789
15890 // Mark this component as ready. This mounts the Layout and new ContentType.
159- this . setState ( { pageUuid, contentTypeComponentSymbol , ready : true , loadingData : false , dataUrl : url } ) ;
91+ this . setState ( { pageUuid, loadingData : false , dataUrl : url } ) ;
16092 }
16193
16294 render ( ) {
95+ // Mark this component as not-ready. This unmounts the Layout and old ContentType.
16396 // Only render if the component is ready.
164- if ( ! this . state . ready ) return null ;
97+ if ( this . entity && ! this . props . renderWhileLoadingData && ! this . entity . isReady ( ) ) return null ;
16598
16699 // Get props.
167100 const Layout = this . props . layout ;
168101
169102 // Get the data and content types with the state properties.
170103 const data = site . getData ( this . state . pageUuid ) ;
171- const ContentType = components . get ( this . state . contentTypeComponentSymbol ) ;
172104
173105 return (
174106 < Layout
@@ -177,12 +109,41 @@ export default class DrupalPage extends Component {
177109 page = { data }
178110 { ...this . props . layoutProps }
179111 >
180- < ContentType
112+ < EntityMapper
113+ mapper = { this . props . mapper }
114+ uuid = { this . state . pageUuid }
115+ asyncMapper = { this . props . asyncMapper }
116+ entityProps = { this . props . pageProps }
181117 page = { data }
182- { ...data }
183- { ...this . props . pageProps }
118+ ref = { ( c ) => { this . entity = c ; } }
184119 />
185120 </ Layout >
186121 ) ;
187122 }
188123}
124+
125+ DrupalPage . propTypes = {
126+ url : PropTypes . string . isRequired ,
127+ layout : PropTypes . oneOfType ( [
128+ PropTypes . func ,
129+ PropTypes . string ,
130+ ] ) ,
131+ mapper : PropTypes . oneOfType ( [
132+ PropTypes . shape ( ) ,
133+ PropTypes . func ,
134+ ] ) . isRequired ,
135+ asyncMapper : PropTypes . bool ,
136+ layoutProps : PropTypes . shape ( ) ,
137+ renderWhileLoadingData : PropTypes . bool ,
138+ pageProps : PropTypes . shape ( ) ,
139+ } ;
140+
141+ DrupalPage . defaultProps = {
142+ layout : Fragment ,
143+ asyncMapper : undefined ,
144+ layoutProps : { } ,
145+ renderWhileLoadingData : false ,
146+ pageProps : undefined ,
147+ } ;
148+
149+ export default DrupalPage ;
0 commit comments