Skip to content

Commit 031f386

Browse files
Merge pull request #61 from headless-ninja/no-static-methods
Replace all static methods with plain functions
2 parents 698d084 + 0345882 commit 031f386

File tree

3 files changed

+126
-133
lines changed

3 files changed

+126
-133
lines changed

packages/hn-react/src/components/DrupalPage.tsx

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import * as PropTypes from 'prop-types';
33
import * as React from 'react';
44
import { SiteConsumer } from '../context/site';
55
import EntityMapper, {
6-
EntityMapper as InnerEntityMapper,
6+
assureComponent,
77
EntityMapperPropsMapper,
8+
getComponentFromMapper,
89
} from './EntityMapper';
910

1011
interface DrupalPageState {
@@ -19,11 +20,11 @@ class DrupalPage extends React.Component<
1920
lastAssuredProps: DrupalPageInnerProps | null = null;
2021

2122
async bootstrap() {
22-
const { uuid } = await DrupalPage.assureData(this.props);
23+
const { uuid } = await assureData(this.props);
2324

2425
if (!this.props.mapper && !this.props.asyncMapper) return;
2526

26-
return InnerEntityMapper.assureComponent({
27+
return assureComponent({
2728
uuid,
2829
mapper: this.props.mapper as any,
2930
asyncMapper: this.props.asyncMapper as any,
@@ -43,7 +44,7 @@ class DrupalPage extends React.Component<
4344

4445
if (!this.props.mapper && !this.props.asyncMapper) return true;
4546

46-
return !!InnerEntityMapper.getComponentFromMapper({
47+
return getComponentFromMapper({
4748
uuid,
4849
mapper: this.props.mapper as any,
4950
asyncMapper: this.props.asyncMapper as any,
@@ -75,15 +76,15 @@ class DrupalPage extends React.Component<
7576
// is ready.
7677
(async () => {
7778
// First, make sure we load the url into the site cache.
78-
const { uuid } = await DrupalPage.assureData(props);
79+
const { uuid } = await assureData(props);
7980

8081
// If in the meantime the props updated, stop.
8182
if (lastRequest !== this.lastRequest) return;
8283

8384
// Make sure the mapper is ready by loading the async component into the mapper
8485
// cache.
8586
if (props.mapper || props.asyncMapper) {
86-
await InnerEntityMapper.assureComponent({
87+
await assureComponent({
8788
uuid,
8889
mapper: props.mapper as any,
8990
asyncMapper: props.asyncMapper as any,
@@ -121,15 +122,6 @@ class DrupalPage extends React.Component<
121122
this.lastRequest = undefined;
122123
}
123124

124-
/**
125-
* This makes sure the data for this url is ready to be rendered.
126-
*/
127-
static async assureData({ url, site }: { url: string; site: Site }) {
128-
const uuid = await site.getPage(url);
129-
130-
return { uuid, pageUuid: uuid };
131-
}
132-
133125
render() {
134126
if (this.state.error) {
135127
throw this.state.error;
@@ -238,6 +230,10 @@ const DrupalPageWrapper = React.forwardRef<DrupalPage, DrupalPageProps>(
238230
),
239231
);
240232

241-
export const assureData = DrupalPage.assureData;
233+
export async function assureData({ url, site }: { url: string; site: Site }) {
234+
const uuid = await site.getPage(url);
235+
236+
return { uuid, pageUuid: uuid };
237+
}
242238

243239
export default DrupalPageWrapper;

packages/hn-react/src/components/EntityMapper.test.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import waitForHnData from '../utils/waitForHnData';
1313
import EntityMapper, {
1414
EntityMapper as InnerEntityMapper,
1515
clearEntityCache,
16+
assureComponent,
1617
} from './EntityMapper';
1718

1819
jest.mock('../utils/site', () => {
@@ -164,9 +165,9 @@ describe('EntityMapper', async () => {
164165
});
165166

166167
test('assure component with mapper not supporting bundle', async () => {
167-
expect(
168-
InnerEntityMapper.assureComponent({ site, uuid, asyncMapper: {} }),
169-
).resolves.toBe(undefined);
168+
expect(assureComponent({ site, uuid, asyncMapper: {} })).resolves.toBe(
169+
undefined,
170+
);
170171
});
171172

172173
async function setupPropsChange() {

packages/hn-react/src/components/EntityMapper.tsx

Lines changed: 110 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -20,113 +20,6 @@ export class EntityMapper extends React.Component<
2020

2121
lastAssuredProps: EntityMapperInnerProps | null = null;
2222

23-
/**
24-
* This gets a component from some mapper data.
25-
* This can also be a promise resolving to a component.
26-
*/
27-
static getComponentOrPromiseFromMapper(
28-
props: EntityMapperInnerProps,
29-
):
30-
| { type: 'component'; value: undefined | React.ReactType }
31-
| { type: 'promise'; value: undefined | (() => ImportReturn) } {
32-
// This gets the entity from the site, based on the uuid.
33-
const entity = props.site.getData(props.uuid);
34-
35-
// This should give back a bundle string, that is used in the mapper.
36-
const bundle = EntityMapper.getBundle(entity);
37-
38-
// If it's not an async mapper, we can just use the 'mapper' prop.
39-
if (!props.asyncMapper) {
40-
return {
41-
type: 'component',
42-
value:
43-
typeof props.mapper === 'function'
44-
? props.mapper(entity, bundle)
45-
: props.mapper[bundle],
46-
};
47-
}
48-
49-
// We check which style of the mapper it is.
50-
const entityComponentMapper =
51-
props.asyncMapper === true ? props.mapper : props.asyncMapper;
52-
const entityComponentResult =
53-
typeof entityComponentMapper === 'function'
54-
? entityComponentMapper(entity, bundle)
55-
: entityComponentMapper[bundle];
56-
57-
return {
58-
type: 'promise',
59-
value: entityComponentResult,
60-
};
61-
}
62-
63-
/**
64-
* This makes sure the data for this url is ready to be rendered.
65-
*/
66-
static async assureComponent(props: EntityMapperInnerProps) {
67-
const component = this.getComponentOrPromiseFromMapper(props);
68-
69-
// If it's not a promise, return.
70-
// Nothing to assure.
71-
if (component.type === 'component') {
72-
return;
73-
}
74-
75-
// If no value was returned from the mapper, we can't assure the component.
76-
if (!component.value) {
77-
return;
78-
}
79-
80-
// Check if we already cached this component.
81-
if (entityCache.has(component.value)) {
82-
return;
83-
}
84-
85-
// If not, we get this entity now.
86-
const entityComponentResult = await component.value();
87-
88-
// We save the entity in the cache.
89-
if (
90-
typeof entityComponentResult === 'object' &&
91-
typeof entityComponentResult.default !== 'undefined'
92-
) {
93-
entityCache.set(component.value, entityComponentResult.default);
94-
} else {
95-
entityCache.set(
96-
component.value,
97-
entityComponentResult as React.ReactType,
98-
);
99-
}
100-
}
101-
102-
/**
103-
* Returns the component if it is availible right now.
104-
* Returns null if the component isn't available, and never will be.
105-
* Returns undefined if the component isn't available, but maybe will be in the future.
106-
*/
107-
static getComponentFromMapper(
108-
props: EntityMapperInnerProps,
109-
): React.ReactType | null | undefined {
110-
const entityComponent = EntityMapper.getComponentOrPromiseFromMapper(props);
111-
112-
if (
113-
entityComponent.type === 'promise' &&
114-
typeof entityComponent.value !== 'undefined'
115-
) {
116-
return entityCache.get(entityComponent.value);
117-
}
118-
if (entityComponent.type === 'component') {
119-
return entityComponent.value || null;
120-
}
121-
return null;
122-
}
123-
124-
static getBundle = entity =>
125-
getNested(
126-
() => `${entity.__hn.entity.type}__${entity.__hn.entity.bundle}`,
127-
'_fallback',
128-
);
129-
13023
/**
13124
* If this component exists in a tree that is invoked with the waitForHnData function, this function is invoked.
13225
* Only after the promise is resolved, the component will be mounted. To keep the data fetched here, we assign the
@@ -135,7 +28,7 @@ export class EntityMapper extends React.Component<
13528
*/
13629
async bootstrap() {
13730
// Make sure that if this is an async component, we have it saved in the entity cache.
138-
return EntityMapper.assureComponent(this.props);
31+
return assureComponent(this.props);
13932
}
14033

14134
lastRequest: symbol | undefined;
@@ -157,7 +50,7 @@ export class EntityMapper extends React.Component<
15750
}
15851

15952
(async () => {
160-
await EntityMapper.assureComponent(this.props);
53+
await assureComponent(this.props);
16154

16255
if (lastRequest !== this.lastRequest) {
16356
return;
@@ -181,7 +74,7 @@ export class EntityMapper extends React.Component<
18174
}
18275

18376
isReady(props = this.props) {
184-
return typeof EntityMapper.getComponentFromMapper(props) !== 'undefined';
77+
return typeof getComponentFromMapper(props) !== 'undefined';
18578
}
18679

18780
render() {
@@ -201,7 +94,7 @@ export class EntityMapper extends React.Component<
20194
return null;
20295
}
20396

204-
const EntityComponent = EntityMapper.getComponentFromMapper(props);
97+
const EntityComponent = getComponentFromMapper(props);
20598

20699
if (EntityComponent === null) {
207100
return null;
@@ -218,7 +111,7 @@ export class EntityMapper extends React.Component<
218111

219112
return (
220113
<EntityComponent
221-
bundle={EntityMapper.getBundle(data)}
114+
bundle={getBundle(data)}
222115
paragraph={data}
223116
entity={data}
224117
{...props.entityProps}
@@ -309,6 +202,109 @@ const EntityMapperWrapper = React.forwardRef<EntityMapper, EntityMapperProps>(
309202
),
310203
);
311204

312-
export const assureComponent = EntityMapper.assureComponent;
313-
314205
export default EntityMapperWrapper;
206+
207+
/**
208+
* This gets a component from some mapper data.
209+
* This can also be a promise resolving to a component.
210+
*/
211+
function getComponentOrPromiseFromMapper(
212+
props: EntityMapperInnerProps,
213+
):
214+
| { type: 'component'; value: undefined | React.ReactType }
215+
| { type: 'promise'; value: undefined | (() => ImportReturn) } {
216+
// This gets the entity from the site, based on the uuid.
217+
const entity = props.site.getData(props.uuid);
218+
219+
// This should give back a bundle string, that is used in the mapper.
220+
const bundle = getBundle(entity);
221+
222+
// If it's not an async mapper, we can just use the 'mapper' prop.
223+
if (!props.asyncMapper) {
224+
return {
225+
type: 'component',
226+
value:
227+
typeof props.mapper === 'function'
228+
? props.mapper(entity, bundle)
229+
: props.mapper[bundle],
230+
};
231+
}
232+
233+
// We check which style of the mapper it is.
234+
const entityComponentMapper =
235+
props.asyncMapper === true ? props.mapper : props.asyncMapper;
236+
const entityComponentResult =
237+
typeof entityComponentMapper === 'function'
238+
? entityComponentMapper(entity, bundle)
239+
: entityComponentMapper[bundle];
240+
241+
return {
242+
type: 'promise',
243+
value: entityComponentResult,
244+
};
245+
}
246+
247+
/**
248+
* This makes sure the data for this url is ready to be rendered.
249+
*/
250+
export async function assureComponent(props: EntityMapperInnerProps) {
251+
const component = getComponentOrPromiseFromMapper(props);
252+
253+
// If it's not a promise, return.
254+
// Nothing to assure.
255+
if (component.type === 'component') {
256+
return;
257+
}
258+
259+
// If no value was returned from the mapper, we can't assure the component.
260+
if (!component.value) {
261+
return;
262+
}
263+
264+
// Check if we already cached this component.
265+
if (entityCache.has(component.value)) {
266+
return;
267+
}
268+
269+
// If not, we get this entity now.
270+
const entityComponentResult = await component.value();
271+
272+
// We save the entity in the cache.
273+
if (
274+
typeof entityComponentResult === 'object' &&
275+
typeof entityComponentResult.default !== 'undefined'
276+
) {
277+
entityCache.set(component.value, entityComponentResult.default);
278+
} else {
279+
entityCache.set(component.value, entityComponentResult as React.ReactType);
280+
}
281+
}
282+
283+
/**
284+
* Returns the component if it is availible right now.
285+
* Returns null if the component isn't available, and never will be.
286+
* Returns undefined if the component isn't available, but maybe will be in the future.
287+
*/
288+
export function getComponentFromMapper(
289+
props: EntityMapperInnerProps,
290+
): React.ReactType | null | undefined {
291+
const entityComponent = getComponentOrPromiseFromMapper(props);
292+
293+
if (
294+
entityComponent.type === 'promise' &&
295+
typeof entityComponent.value !== 'undefined'
296+
) {
297+
return entityCache.get(entityComponent.value);
298+
}
299+
if (entityComponent.type === 'component') {
300+
return entityComponent.value || null;
301+
}
302+
return null;
303+
}
304+
305+
function getBundle(entity) {
306+
return getNested(
307+
() => `${entity.__hn.entity.type}__${entity.__hn.entity.bundle}`,
308+
'_fallback',
309+
);
310+
}

0 commit comments

Comments
 (0)