-
-
Notifications
You must be signed in to change notification settings - Fork 36
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
Feat/html content #71
Conversation
@@ -10,4 +10,5 @@ export interface AnimatePresenceProps { | |||
as?: string | |||
custom?: any |
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 custom
property is currently typed as any
, which can lead to potential type safety issues as it bypasses TypeScript's static type checking. It's recommended to define a more specific type or at least use unknown
if the type is not determinable, which would enforce type checking at the usage points.
Recommended Change:
custom?: unknown
@@ -10,4 +10,5 @@ export interface AnimatePresenceProps { | |||
as?: string |
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 property as
is ambiguously named, which might cause confusion about its purpose. It's better to use a more descriptive name that clearly indicates its role, such as elementType
or componentType
, especially if it's used to specify the type of component or HTML tag to render.
Recommended Change:
elementType?: string
@@ -31,7 +31,7 @@ export function nodeGroup(): NodeGroup { | |||
unsubscribe() | |||
subscriptions.delete(node) | |||
} | |||
// dirtyAll() | |||
dirtyAll() |
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.
Performance Concern
Calling dirtyAll
on every node removal (line 34) can lead to performance issues in scenarios where the node set is large. This is because it triggers the notify
function for all nodes, which might be computationally expensive.
Recommendation:
Consider optimizing this by determining if all nodes need to be notified upon the removal of one node. If not, modify the logic to selectively update nodes based on dependency or impact, or debounce the updates if multiple removals are expected in short sequences.
unsubscribe() | ||
subscriptions.delete(node) | ||
} |
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.
Lack of Error Handling
The unsubscribe function (lines 31-33) is called without any error handling. If this function throws an error, it could lead to unhandled exceptions which might crash the application or lead to unexpected behavior.
Recommendation:
Wrap the unsubscribe call in a try-catch block to handle potential errors gracefully. Log the error or handle it according to the application's error management strategy.
export * from './animate-presence' | ||
export * from './motion-config' |
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.
Using wildcard exports (export * from ...
) can lead to unintentional exposure of internal modules and makes it difficult to track dependencies. This can compromise the maintainability and security of the codebase.
Recommendation: Explicitly list the exports from each module. This approach improves clarity, makes the code easier to refactor, and helps in maintaining a clear API surface.
this.didUpdate() | ||
globalProjectionState.hasEverUpdated = true |
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.
Direct manipulation of a global state (globalProjectionState.hasEverUpdated = true
) within the mount
method can lead to unintended side effects if this state is shared across multiple components or parts of the application. Consider encapsulating this state change within a method or using a state management pattern that isolates side effects and makes the state changes more predictable.
else { | ||
this.didUpdate() | ||
} |
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 else
block in the unmount
method calls didUpdate()
unconditionally, which could lead to unexpected behavior if didUpdate()
has side effects or if it's not intended to be called in this context. It's recommended to add specific conditions or checks before calling such methods, or to ensure that the method itself handles being called in this context appropriately.
@@ -33,7 +38,7 @@ export class MotionState { | |||
animate: true, | |||
} | |||
|
|||
// Depth in component tree | |||
// Depth in component tree for lifecycle ordering | |||
public depth: number |
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 depth
property is used to manage the depth of the component in the component tree, which is crucial for lifecycle ordering. However, it is not initialized in the constructor, which could lead to it being undefined
if accessed before being set.
Recommendation: Initialize depth
in the constructor to ensure it always has a valid value, reducing the risk of runtime errors.
get context() { | ||
if (!this._context) { | ||
const handler = { |
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 context
getter uses a proxy to manage context inheritance, which introduces additional complexity and overhead. While this provides a flexible way to handle context, it might be over-engineered for simpler use cases and can impact performance due to the dynamic nature of proxy handling.
Recommendation: Consider simplifying the context management if the use cases are straightforward, or ensure that the benefits of using a proxy justify its overhead. Document the reasons and scenarios where this complexity is necessary.
packages/motion/src/state/utils.ts
Outdated
export function isAnimateChanged(oldOptions: Options, newOptions: Options): boolean { | ||
const oldAnimate = oldOptions.animate | ||
const newAnimate = newOptions.animate | ||
|
||
if (oldAnimate === newAnimate) | ||
return false | ||
if (!oldAnimate || !newAnimate) | ||
return true | ||
|
||
if (typeof oldAnimate !== typeof newAnimate) | ||
return true | ||
|
||
if (typeof oldAnimate === 'string' || typeof oldAnimate === 'boolean') | ||
return oldAnimate !== newAnimate | ||
|
||
// Compare object keys and values | ||
const oldKeys = Object.keys(oldAnimate) | ||
const newKeys = Object.keys(newAnimate) | ||
|
||
if (oldKeys.length !== newKeys.length) | ||
return true | ||
|
||
return oldKeys.some((key) => { | ||
const oldVal = oldAnimate[key] | ||
const newVal = newAnimate[key] | ||
return oldVal !== newVal | ||
&& (typeof oldVal === 'number' | ||
? Math.abs(oldVal - newVal) > Number.EPSILON | ||
: true) | ||
}) | ||
} |
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 function isAnimateChanged
performs multiple property accesses and manual comparisons which can be optimized. Consider using a deep comparison utility like lodash.isEqual
for comparing the animate
objects. This would not only simplify the code but also potentially improve performance by handling edge cases more efficiently.
Suggested Change:
Replace the manual key and value comparison with:
return !_.isEqual(oldAnimate, newAnimate);
Added unwrapElement prop for handling nested element animations
Enhanced LayoutFeature lifecycle management