Make component keys configurable to optimize dynamic rendering#806
Merged
Make component keys configurable to optimize dynamic rendering#806
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This pull request introduces explicit component keys to control re-rendering behavior during updates. Previously, all components used random UUIDs as keys, causing them to re-render on every update. Now, components can be assigned explicit keys (constant or dynamic) to optimize rendering by skipping updates when keys haven't changed.
- Added
identifiedBy()methods toComponentBuilderfor setting explicit component keys - Modified component rendering logic to use key comparison for determining update necessity
- Updated
IFSlotRenderContextcreation to include component reference for key evaluation
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| inventory-framework-api/src/main/java/me/devnatan/inventoryframework/component/ComponentBuilder.java | Added three experimental identifiedBy() method signatures for setting component keys |
| inventory-framework-api/src/main/java/me/devnatan/inventoryframework/component/ItemComponent.java | Replaced constant UUID key with dynamic keyFactory function and lastKey tracking; updated render() and updated() logic to use key comparison |
| inventory-framework-api/src/main/java/me/devnatan/inventoryframework/context/IFSlotContext.java | Added getComponent() method to expose component reference in slot contexts |
| inventory-framework-api/src/main/java/me/devnatan/inventoryframework/context/IFSlotClickContext.java | Removed getComponent() method (moved to parent interface IFSlotContext) |
| inventory-framework-api/src/main/java/me/devnatan/inventoryframework/internal/ElementFactory.java | Updated createSlotRenderContext() signature to accept Component parameter |
| inventory-framework-core/src/main/java/me/devnatan/inventoryframework/component/DefaultComponentBuilder.java | Implemented identifiedBy() methods and added RANDOM_KEY_FACTORY constant for default key generation |
| inventory-framework-core/src/main/java/me/devnatan/inventoryframework/context/AbstractIFContext.java | Updated slot render context creation to pass component reference |
| inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/component/BukkitItemComponentBuilder.java | Added keyFactory parameter handling and default to RANDOM_KEY_FACTORY when null |
| inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/context/SlotRenderContext.java | Added component field and getComponent() implementation |
| inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/internal/BukkitElementFactory.java | Updated createSlotRenderContext() to pass component parameter |
| inventory-framework-platform-minestom/src/main/kotlin/me/devnatan/inventoryframework/component/MinestomItemComponentBuilder.kt | Added keyFactory parameter handling with Kotlin syntax, converted constructor parameters to named arguments |
| inventory-framework-platform-minestom/src/main/kotlin/me/devnatan/inventoryframework/context/SlotRenderContext.kt | Added _component parameter and getComponent() implementation |
| inventory-framework-platform-minestom/src/main/kotlin/me/devnatan/inventoryframework/internal/MinestomElementFactory.kt | Updated createSlotRenderContext() to pass component parameter |
| inventory-framework-platform/src/test/java/me/devnatan/inventoryframework/component/TestItemComponentBuilder.java | Added keyFactory parameter to test mock builder |
| inventory-framework-test/src/main/java/me/devnatan/inventoryframework/internal/MockElementFactory.java | Updated mock createSlotRenderContext() to accept and mock component parameter |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…mework/component/ItemComponent.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Natan Vieira <24600258+devnatan@users.noreply.github.com>
…mework/component/ItemComponent.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Natan Vieira <24600258+devnatan@users.noreply.github.com>
…entory-framework into feat/component-keys
…mework/component/ItemComponent.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Natan Vieira <24600258+devnatan@users.noreply.github.com>
…mework/component/ItemComponent.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Natan Vieira <24600258+devnatan@users.noreply.github.com>
…mework/component/ItemComponent.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Natan Vieira <24600258+devnatan@users.noreply.github.com>
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Component keys are used to identify components and decide whether they should be re-rendered when a view-wide, context-wide, slot or component update occurs.
Previously, components always generated a random internal key (a UUID). This meant that on every full update, all dynamic components were treated as changed — forcing a re-render even when nothing relevant had changed.
Current Behavior (Before This PR)
In the example below:
counterStateis incremented every time the scheduled update triggers.New Behavior (After This PR)
Component keys can now be explicitly defined using
identifiedBy.Although they can also be used for lookup (e.g., via Refs API), their primary purpose is to control whether a component should be re-rendered.
Inventory Framework considers a component dynamic if:
displayIf,hideIf),updateOnStateChange, oronRender,renderWith, orwithItem(() -> ...).Dynamic components are evaluated during rendering to decide whether they should update. One of the final checks is the component key: if it changes, the component re-renders; if not, it stays as-is.
Before this PR the internal key was always random, so dynamic components were always treated as changed, causing unnecessary re-renders.
With identifiedBy, you can now stabilize that key:
In this case, even though the scheduled update fires, the component will only re-render if its key changes.
Making the Component Re-Render Explicitly
If you want the previous behavior (always re-render), simply provide a changing key or do not provide any key:
This mimics the old random-UUID behavior, but now you have full control over when the key changes — and therefore when the component re-renders.
See Scheduled Updates.