feat: multiple roots and props

This commit is contained in:
cha0s 2022-03-13 10:53:11 -05:00
parent 55aaa1cddf
commit 677bc593cc
4 changed files with 34 additions and 12 deletions

View File

@ -16,10 +16,19 @@ export default {
/**
* Define root-level React components that are mounted as siblings on `#main`.
* Note: `req` will be only be defined when server-side rendering.
*
* Return either a React component or an array whoe elements must either be a React component
* or an array of two elements where the first element is the component and the second element
* is the props passed to the component.
* @param {http.ClientRequest} req The HTTP request object.
*/
'@flecks/react.roots': (req) => {
// Note that we're not returning `<Component />`, but `Component`.
return [
Component,
[SomeOtherComponent, {prop: 'value'}]
];
// You can also just:
return Component;
},
},

View File

@ -0,0 +1,15 @@
import React from 'react';
export default (implementations) => (
Object.entries(implementations)
.map(([fleck, ComponentOrComponentsOrTuples]) => (
[].concat([ComponentOrComponentsOrTuples]).map((ComponentOrTuple, i) => {
const key = `${fleck}(${i})`;
if (Array.isArray(ComponentOrTuple)) {
return React.createElement(ComponentOrTuple[0], {key, ...ComponentOrTuple[1]});
}
return React.createElement(ComponentOrTuple, {key});
})
))
.flat()
);

View File

@ -9,6 +9,7 @@ export {hot} from 'react-hot-loader';
// eslint-disable-next-line import/no-extraneous-dependencies, import/no-unresolved
export {default as FlecksContext} from '@flecks/react/context';
export {default as gatherComponents} from './gather-components';
export {default as useEvent} from './hooks/use-event';
export {default as useFlecks} from './hooks/use-flecks';
export {default as usePrevious} from './hooks/use-previous';

View File

@ -4,11 +4,13 @@ import React from 'react';
// eslint-disable-next-line import/no-extraneous-dependencies
import FlecksContext from '@flecks/react/context';
import gatherComponents from './gather-components';
const debug = D('@flecks/react/root');
export default async (flecks, req) => {
const Roots = flecks.invoke('@flecks/react.roots', req);
debug('roots: %O', Object.keys(Roots));
debug('roots: %O', Roots);
const Providers = await flecks.invokeSequentialAsync('@flecks/react.providers', req);
const FlattenedProviders = [];
for (let i = 0; i < Providers.length; i++) {
@ -19,21 +21,16 @@ export default async (flecks, req) => {
}
debug('providers: %O', FlattenedProviders);
return () => {
const children = Object.entries(Roots)
.map(([key, Component]) => React.createElement(Component, {key}));
const AllProviders = [
[FlecksContext.Provider, {value: flecks}],
]
.concat(FlattenedProviders);
const RootElements = AllProviders
.reverse()
.reduce((children, [Provider, props], i) => [
const RootElements = [[FlecksContext.Provider, {value: flecks}]]
.concat(FlattenedProviders)
.reduceRight((children, [Provider, props], i) => [
React.createElement(
Provider,
{key: `@flecks/react/provider(${AllProviders.length - (i + 1)})`, ...props},
// eslint-disable-next-line react/no-array-index-key
{key: `@flecks/react/provider(${i})`, ...props},
children,
),
], children);
], gatherComponents(Roots));
return RootElements[0];
};
};