Skip to content
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

fix: enable next.js 14 support and add some upstream fixes #2613

Merged
merged 2 commits into from
Apr 25, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 22 additions & 14 deletions src/react/core/create-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ export interface Options<I extends HTMLElement, E extends EventNames = {}> {
elementClass: Constructor<I>;
events?: E;
displayName?: string;
renderAttributesOnCreate?: boolean;
}

type Constructor<T> = { new (): T };
Expand Down Expand Up @@ -181,8 +180,10 @@ const setProperty = <E extends Element>(
) => {
const event = events?.[name];
// Dirty check event value.
if (event !== undefined && value !== old) {
addOrUpdateEventListener(node, event, value as (e?: Event) => void);
if (event !== undefined) {
if (value !== old) {
addOrUpdateEventListener(node, event, value as (e?: Event) => void);
}
return;
}
// But don't dirty check properties; elements are assumed to do this.
Expand Down Expand Up @@ -253,7 +254,7 @@ export const createComponent = <I extends HTMLElement, E extends EventNames = {}
type Props = ComponentProps<I, E>;

const ReactComponent = React.forwardRef<I, Props>((props, ref) => {
const prevPropsRef = React.useRef<Props | null>(null);
const prevElemPropsRef = React.useRef(new Map());
const elementRef = React.useRef<I | null>(null);

// Props to be passed to React.createElement
Expand Down Expand Up @@ -308,20 +309,26 @@ export const createComponent = <I extends HTMLElement, E extends EventNames = {}
if (elementRef.current === null) {
return;
}
for (const prop in elementProps) {
const newElemProps = new Map();
for (const key in elementProps) {
setProperty(
elementRef.current,
prop,
props[prop],
prevPropsRef.current ? prevPropsRef.current[prop] : undefined,
key,
props[key],
prevElemPropsRef.current.get(key),
events,
);
prevElemPropsRef.current.delete(key);
newElemProps.set(key, props[key]);
}
// Note, the spirit of React might be to "unset" any old values that
// are no longer included; however, there's no reasonable value to set
// them to so we just leave the previous state as is.

prevPropsRef.current = props;
// "Unset" any props from previous render that no longer exist.
// Setting to `undefined` seems like the correct thing to "unset"
// but currently React will set it as `null`.
// See https://github.com/facebook/react/issues/28203
for (const [key, value] of prevElemPropsRef.current) {
setProperty(elementRef.current, key, undefined, value, events);
}
prevElemPropsRef.current = newElemProps;
});

// Empty dependency array so this will only run once after first render.
Expand All @@ -335,7 +342,8 @@ export const createComponent = <I extends HTMLElement, E extends EventNames = {}
// element properties in a special bag to be set by the server-side
// element renderer.
if (
React.createElement.name === 'litPatchedCreateElement' &&
(React.createElement.name === 'litPatchedCreateElement' ||
(globalThis as unknown as { litSsrReactEnabled: boolean }).litSsrReactEnabled) &&
Object.keys(elementProps).length
) {
// This property needs to remain unminified.
Expand Down
Loading