From faf6d94cb83ef8025929ce8801ce3db22c0b3415 Mon Sep 17 00:00:00 2001 From: Alexandre Mouton-Brady <amoutonbrady@gmail.com> Date: Tue, 2 Feb 2021 21:57:42 +0100 Subject: [PATCH] :bug: Fix bug with createApp providers --- playground/index.html | 1 - playground/index.tsx | 43 +++++++++++++++++++++++++++++++++++++++++-- src/createApp.tsx | 38 ++++++++++++++++++++++++-------------- 3 files changed, 65 insertions(+), 17 deletions(-) diff --git a/playground/index.html b/playground/index.html index 3a107da..58afdd2 100644 --- a/playground/index.html +++ b/playground/index.html @@ -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> diff --git a/playground/index.tsx b/playground/index.tsx index 6715f39..fbc5be9 100644 --- a/playground/index.tsx +++ b/playground/index.tsx @@ -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' }); @@ -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> @@ -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'); diff --git a/src/createApp.tsx b/src/createApp.tsx index 8c13c3e..a26a18a 100644 --- a/src/createApp.tsx +++ b/src/createApp.tsx @@ -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 { /** @@ -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: @@ -49,19 +56,21 @@ 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 = { @@ -69,10 +78,11 @@ export function createApp<T extends unknown>(app: T) { 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); }, };