fix: safe element merging via useRender#389
Conversation
🦋 Changeset detectedLatest commit: 58bbc75 The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Summary of ChangesHello @noahchoii, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses critical React reconciliation issues caused by the previous Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
|
@SimYunSup Since it seems similar to what you worked on in this PR, I'm leaving a comment! |
There was a problem hiding this comment.
Code Review
This pull request introduces a new createDefaultElement utility to enhance component customizability by allowing ReactNode children to be cloned and augmented with default props, replacing the previous createSlot utility. This change impacts numerous components across @vapor-ui/core, including Breadcrumb, Checkbox, Dialog, IconButton, Menu, MultiSelect, NavigationMenu, Pagination, Popover, Radio, Select, Sheet, Switch, and Toast. Specifically, it refactors how default icons and nested elements are rendered, enabling users to provide custom React elements while retaining default styling and behavior. For instance, IconButton and Checkbox now support arbitrary children, and Toast icons can be customized. Additionally, the styling for IconButton and Pagination icons has been updated to use dynamic sizing based on parent elements, and the project's React dependencies have been upgraded from v17 to v18, along with corresponding @types/react and @types/react-dom updates.
|
✅ All tests passed!
Click here if you need to update snapshots. |
|
If |
|
I had initially thought that creating a custom utility function would be preferable to using However, I reconsidered and changed it because I realized there are advantages to using |
create-default-elementuseRender
| props: { | ||
| children: ( | ||
| <> | ||
| {overlay} | ||
| {popup} | ||
| </> | ||
| ), | ||
| }, |
There was a problem hiding this comment.
LGTM
NOTE: Due to the internal implementation of useRender, where the props merge order is mergeProps(props, render.props), if children are included in portalElement or overlayElement, the children injected internally may be overwritten.
<DialogPopup portalElement={<CustomPortal>something</CustomPortal>} />However, this is how useRender works, and since there's almost no use case for directly passing children to Portal, it's probably best to just acknowledge this and move on.
Description of Changes
1. Motivation
The existing
create-slotutility functioned by defining a new component during the render phase. This caused the component reference to change on every re-render, leading to React identifying it as a different component during Reconciliation.This resulted in several critical issues:
openstate in a Popup) was lost because a fresh instance was created, causing the UI to behave unexpectedly (e.g., closing immediately or losing context).2. Changes
I introduced a new utility,
createDefaultElement, to replace the problematic logic.cloneElementto clone the existing element and merge props.3. Trade-offs & Notes
1) Usage Change (JSX → Element)
Since the new utility returns a React Element instance rather than a Component definition, you must render the variable directly instead of using JSX syntax.
2) Style Handling in
IconButtonTo prevent unintended HTML attributes (like
widthorheight) from being applied to non-SVG children (e.g.,Textcomponents), default dimensions are now applied viaclassNameinstead of inline attributes.<HeartIcon width="36px" />), the CSS class may take precedence, and the inline attribute might be ignored.cssprop object to handle style overrides more flexibly in the future.Checklist
Before submitting the PR, please make sure you have checked all of the following items.