Skip to content
This repository has been archived by the owner on Mar 15, 2023. It is now read-only.

Commit

Permalink
🐛 Fix bug with createApp providers
Browse files Browse the repository at this point in the history
  • Loading branch information
amoutonbrady committed Feb 2, 2021
1 parent 2668a34 commit faf6d94
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 17 deletions.
1 change: 0 additions & 1 deletion playground/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app"></div>
Expand Down
43 changes: 41 additions & 2 deletions playground/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { Router, Route, RouteDefinition, Link } from 'solid-app-router';
import { Component } from 'solid-js';
import { MetaProvider, Title } from 'solid-meta';
import { createApp, createStore, createGlobalState, createGlobalSignal } from '../src';

const [globalState, setGlobalState] = createGlobalState({ name: 'hello' });
Expand All @@ -12,11 +15,13 @@ const [Provider, useProvider] = createStore({

const Name = () => <h1>Watch me also change name here: {globalState.name}</h1>;

const App = () => {
const Home = () => {
const [state, { inc }] = useProvider();

return (
<>
<Title>Home</Title>

<h1>
My name is: {globalState.name} and I'm: {globalSignal()}
</h1>
Expand All @@ -41,4 +46,38 @@ const App = () => {
);
};

createApp(App).use(Provider).mount('#app');
const About = () => (
<>
<Title>About</Title>
<h1>About</h1>
</>
);

const App: Component<{ name: string }> = (props) => {
return (
<>
<Link href="/">Home</Link>
<Link href="/about">About</Link>
<hr />
<h1>Global name {props.name}</h1>
<Route />
</>
);
};

const routes: RouteDefinition[] = [
{
path: '/',
component: Home,
},
{
path: '/about',
component: About,
},
];

createApp(App, { name: 'Alexandre' })
.use(Router, { routes })
.use(MetaProvider)
.use(Provider)
.mount('#app');
38 changes: 24 additions & 14 deletions src/createApp.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { JSX, Component } from 'solid-js';
import { createComponent, render } from 'solid-js/web';
import type { Component, JSX } from 'solid-js';
import { createComponent as component, render } from 'solid-js/web';

interface App {
/**
Expand All @@ -19,11 +19,18 @@ interface App {
*/
mount(domElement: HTMLElement | string): ReturnType<typeof render>;
}

interface Provider {
provider: Component;
opts?: Record<string, any>;
}

interface MergeParams {
app: (props?: Record<string, any>) => JSX.Element;
props: Record<string, any>;
providers: Provider[];
}

/**
* This utils function automatically merge the provider in the order they
* were provided. It turns the following calls:
Expand All @@ -49,30 +56,33 @@ interface Provider {
* document.querySelector('#app')
* )
*/
function mergeProviders(app: () => Element, providers: Provider[]) {
return providers.reduceRight<JSX.Element | undefined>((application, { provider, opts }) => {
return createComponent(provider, {
...opts,
function mergeProviders({ app, props = {}, providers }: MergeParams) {
return providers.reduceRight(
(application, { provider, opts = {} }) => () =>
component(provider, {
...opts,

get children() {
return application || createComponent(app, {});
},
});
}, undefined);
get children() {
return application();
},
}),
() => component(app, props),
);
}

export function createApp<T extends unknown>(app: T) {
export function createApp<AppProps>(app: (props?: AppProps) => JSX.Element, props?: AppProps) {
const providers: Provider[] = [];

const _app: App = {
use(provider, opts = {} as any) {
providers.push({ provider, opts });
return _app;
},

mount(dom) {
const application = mergeProviders(app as () => Element, providers);
const application = mergeProviders({ app, props, providers });
const root = typeof dom === 'string' ? document.querySelector(dom) : dom;
return render(() => application, root);
return render(application, root);
},
};

Expand Down

0 comments on commit faf6d94

Please sign in to comment.