-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds support for root component #1009
Conversation
d9e6693
to
790bd33
Compare
{=# rootComponent.isDefined =} | ||
<{= rootComponent.importIdentifier =}>{router}</{= rootComponent.importIdentifier =}> | ||
{=/ rootComponent.isDefined =} | ||
{=^ rootComponent.isDefined =} | ||
{router} | ||
{=/ rootComponent.isDefined =} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: What about:
{=# rootComponent.isDefined =} | |
<{= rootComponent.importIdentifier =}>{router}</{= rootComponent.importIdentifier =}> | |
{=/ rootComponent.isDefined =} | |
{=^ rootComponent.isDefined =} | |
{router} | |
{=/ rootComponent.isDefined =} | |
{=# rootComponent.isDefined =} | |
<{= rootComponent.importIdentifier =}> | |
{=/ rootComponent.isDefined =} | |
{router} | |
{=# rootComponent.isDefined =} | |
</{= rootComponent.importIdentifier =}> | |
{=/ rootComponent.isDefined =} |
is this maybe nicer / more composable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It will be easier to add new user defined wrappers, but will we have the need to add them in the future?
Your approach has extra whitespace in the output when not using rootComponent
e.g. {router}
😂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I know but I gave up on formatting, we can't do it 100% anyway.
I think what I wrote is more explicit about "we are just wrapping it into this".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense, I'll probably need to give up on output formatting as well 😢
Maybe in the future, one of our build steps can be running everything through Prettier auto-format and then the users will get super nice output :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes that is probably what we will want to do! Or we will give up on it completely. But I like the idea of prettier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated here: 207806c
Nice job -> your first extension of Wasp language itself :D! Oh one thing is missing though -> docs, right? Let's add them in this PR, no reason to do them in separate PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add docs?
I've updated the docs in the meantime, check the last commit 🙂 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Some small comments, resolve as you find fit and you can merge!
web/docs/language/features.md
Outdated
export default async function Root({ children }) { | ||
return ( | ||
<Provider store={store}> | ||
<App>{children}</App> | ||
</Provider> | ||
) | ||
} | ||
|
||
function App({ children }) { | ||
return ( | ||
<div> | ||
<h1>My App</h1> | ||
{children} | ||
</div> | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WHy do we need this extra App here? Can't we just have Root
render children directly in Provider component and that is it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to offer a more elaborate example where we have the Provider
wrapping and some <App />
compnent (which is how you'll see it's done in the Redux docs).
This also works:
export default async function Root({ children }) {
return (
<Provider store={store}>
{children}
</Provider>
)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok! It is good to give exapmles, but I sometimes have the need to reduce them if possible, to make maintainance simpler. But this is probably ok it is not so complex. Unless this might confused them -> do I have to use this App inside this thing? I don't know, your call!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll provide two use-case examples (Layout + Providers) and a one more complex where both are coming together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated here: 207806c
mkTmplDataForExtImport :: Maybe ExtImport -> Aeson.Value | ||
mkTmplDataForExtImport maybeExtImport = maybe notDefinedValue mkTmplData maybeExtImport |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function encapsulates a common pattern.
If I understand correctly, we're using it for all ext imports. Do you think it makes sense to put it in a more public place and reuse?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be extracted to a common function in Wasp.Generator.JsImport
and then it can be specialized in Wasp.Generator.WebAppGenerator.JsImport
and Wasp.Generator.ServerGenerator.JsImport
.
In the web app templates, this pattern is actually only used in this file, but in the server templates it's used more.
I'll extract the pattern in this PR and apply it to WebApp
only. I'll do the same for server templates in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now have:
Wasp.Generator.JsImport
->jsImportToTmplData
which generates appropriateJSON
for usage in templates when we need to do something with import statementsWasp.Generator.WebAppGenerator.JsImport
->extImportToJsImportTmplData
which uses the above method to convert anExtImport
toJSON
template data
We should add in a separate PR:
Wasp.Generator.ServerGenerator.JsImport
->extImportToJsImportTmplData
- use the new function to refactor the way we generate template data for JS import statements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To keep in line with naming conventions for functions (i.e., they should be verbs) and what we already have (like this guy here*), I suggest renaming this to something like makeImportJson
.
The "functions should be verbs" applies to other places as well.
* Although that name could have been better as well :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a number of these "tranform" functions in our codebase, and I kinda like this convetion of <A>To<B>
naming.
Some examples I found in our codebase:
kebabToCamelCase
sourceSpanToRegion
lspPositionToOffset
extImportToJsImport
(that's mine)
What about extImportToImportJson
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true, we have several of those.
Anyway, choose whatever you like best.
Purely FYI, this is my order of preference:
makeExtImportJson
extImportToImportJson
extImportToJsImport
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy to inform you that I went with your second favourite option 🎉
Root component
Fixes #77
This PR introduces
rootComponent
in theapp.client
dictionary in Wasp lang which will help users to define their root React component.rootComponent
is of typeExtImport
which is an import statement from user defined files.This enables the user to do:
src/client/App.jsx
which exports a componentRedux
orChakraProvider
https://chakra-ui.com/getting-startedWe then use their root component to wrap the
router
in the app'sindex.js
.