-
-
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
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 commentThe 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 CopyUSButton = (props) => { | ||
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 commentThe 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 |
||
...rest | ||
} = props; | ||
const record = g.useRecordContext(props); | ||
const createPath = g.useCreatePath(); | ||
const pathname = createPath({resource: "rhymes_us", type: "create"}); | ||
props = { | ||
component: g.Link, | ||
to: ( | ||
record | ||
? { | ||
pathname, | ||
search: g.stringify({source: JSON.stringify(record)}), | ||
state: {_scrollToTop: scrollToTop}, | ||
} | ||
: pathname | ||
), | ||
label: label, | ||
onClick: stopPropagation, | ||
...sanitizeRestProps(rest) | ||
}; | ||
return g.createElement(g.Button, props, icon); | ||
}; | ||
|
||
// useful to prevent click bubbling in a datagrid with rowClick | ||
const stopPropagation = e => e.stopPropagation(); | ||
|
||
const sanitizeRestProps = ({resource, record, ...rest}) => rest; | ||
|
||
export const components = {CopyUSButton: CopyUSButton}; |
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.
cd aiohttp-admin
.pip install -r requirements.txt
cd admin-js; yarn install; yarn build
cd ../examples
PYTHONPATH='..' python simple.py
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.