-
-
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
Closed
Closed
Dynamic component #2 #767
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
export const g = {"Queue": null, "Link": null, "stringify": null, "Button": null, | ||
"createElement": null, "useRecordContext": null, "useCreatePath": null, | ||
"useResourceContext": null} | ||
|
||
const CustomCloneButton = (props) => { | ||
const { | ||
label = "My custom clone", | ||
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 resource = g.useResourceContext(props); | ||
const record = g.useRecordContext(props); | ||
const createPath = g.useCreatePath(); | ||
const pathname = createPath({resource, 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 = {CustomCloneButton: CustomCloneButton}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.