-
-
Notifications
You must be signed in to change notification settings - Fork 46
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
Dynamic component #2 #767
Dynamic component #2 #767
Conversation
examples/custom-clone.js
Outdated
export const g = {"Queue": null, "Link": null, "stringify": null, "Button": null, | ||
"createElement": null, "useRecordContext": null, "useCreatePath": null} |
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 start by defining a global object that contains all the react functions etc. that we want as the keys, with values initialised to null.
const { | ||
label = "Copy to US", | ||
scrollToTop = true, | ||
icon = g.createElement(g.Queue), |
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.
Then we use the functions from the global object the same as we would if we had imported them normally.
We can't use JSX here, because it will evaluate to null
at compile time and not work at all.
for (const k of Object.keys(mod.g)) | ||
mod.g[k] = COMPONENTS[k] |
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.
The main application, after dynamically importing the module, simply loops through the module's global object and inserts all the functions it asks for.
This means the module's components will be using the actual same react functions as the main application, and therefore have the same context etc. required to make the component work correctly.
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.
@Dreamsorcerer coming from SO as discussed. Would like to have docs or steps to maybe set up an environment where I can reproduce your issue and try out things. If that's too much work you should not bother because there's a tiny chance I can really take a deep look at it. Will try tho. Thanks
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.
Thanks, the base project is in Python, if you're on Mac/Linux then you'll already have it installed, so should only take a couple of minutes to run.
- Clone this branch and
cd aiohttp-admin
. - Install python dependencies:
pip install -r requirements.txt
- Build the JS module:
cd admin-js; yarn install; yarn build
- Try the example:
cd ../examples
PYTHONPATH='..' python simple.py
- Go to http://localhost:8080/admin
- You can login with admin/admin and see the basic project working.
If you click on one of the rows to get to the show view, you'll see the custom button created in the examples:
The custom button is loaded from examples/custom-button.js. If you want to try building something with yarn or similar, you can just create a new project and copy the output file over custom-button.js.
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.
@Anthony-E-B I had an idea, maybe you might know if it's workable and how to go about it?
I was thinking that maybe I could find a way to replace react in a project's dependencies with some kind of shim.
e.g. I want to use a 3rd-party component, and they have react listed as a dependency. In my build configuration, I replace react with my custom library (no idea how this is done, but presumably it must be possible so people can use patched versions of a library etc.). That custom library has all the same functions as react, except that it will actually proxy the calls to the main application.
So, essentially we replace react in the build script in order to build the component without react being in the compiled module. Then when we import that module from the main application, the module will send all those react calls to the main application, which will use the version of react already compiled in there.
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.
Maybe this can be used for replacing react:
https://github.com/nerdchacha/module-replace-webpack-plugin
Although doesn't appear to be maintained. Then I just need to figure out a way to build the shim and proxy the calls through.
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.
@Anthony-E-B If you're interested, I've come up with a solution in #804.
I think the only thing that would be nice to improve, is having some way to import react-admin/react-router-dom components when they are not included in the shim (because adding all of react-admin to the shim increases the application size by 400KB) with some kind of fallback mechanism in the build process.
Codecov Report
@@ Coverage Diff @@
## master #767 +/- ##
=======================================
Coverage 97.45% 97.45%
=======================================
Files 15 15
Lines 2118 2118
Branches 334 334
=======================================
Hits 2064 2064
Misses 26 26
Partials 28 28
Flags with carried forward coverage won't be shown. Click here to find out more. 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
This version works, and has the advantage that a module for a custom component will only be ~1 KB. Another advantage is that (if the component doesn't import anything outside of the global object), then these components can be written as vanilla JS without any compiler.
However, the disadvantages are that it is quite awkward, won't work with existing 3rd-party components and JSX can't be used with it. If a component requires other react/react-admin functions, which are not already imported in the main application, then it may also not work.