diff --git a/.changeset/happy-seas-tie.md b/.changeset/happy-seas-tie.md new file mode 100644 index 0000000..b59e016 --- /dev/null +++ b/.changeset/happy-seas-tie.md @@ -0,0 +1,5 @@ +--- +'@unisonjs/core': patch +--- + +Fix component reloading on file change (hmr/fast refresh) diff --git a/packages/core/src/context.ts b/packages/core/src/context.ts index 5d4035d..c6dff65 100644 --- a/packages/core/src/context.ts +++ b/packages/core/src/context.ts @@ -58,6 +58,9 @@ export type Event = { }; type OnFlushCallback = (event: Partial) => void; +export function isFastRefresh() { + return !!(typeof window !== 'undefined' && window.__UNISON_REFRESH__); +} class OnBeforeMount extends React.Component<{ hooks: Function[] }> { componentWillUnmount(): void { @@ -162,7 +165,7 @@ class Context { this.#nbExecution++; this.#isRunning = true; this.#scope.on(); - if (this.isFastRefresh() && !window.__UNISON_REFRESH__.root) { + if (isFastRefresh() && !window.__UNISON_REFRESH__.root) { window.__UNISON_REFRESH__.root = this; } } @@ -366,7 +369,7 @@ class Context { this.#updated = false; this.#isRunning = false; this.#scope.off(); - if (this.isFastRefresh() && window.__UNISON_REFRESH__.root === this) { + if (isFastRefresh() && window.__UNISON_REFRESH__.root === this) { window.__UNISON_REFRESH__ = undefined; } switchToAuto(); @@ -394,9 +397,6 @@ class Context { return this.#executed; } - isFastRefresh() { - return !!(typeof window !== 'undefined' && window.__UNISON_REFRESH__); - } executed() { this.#executed = true; diff --git a/packages/core/src/management.ts b/packages/core/src/management.ts index 083a88e..6726f53 100644 --- a/packages/core/src/management.ts +++ b/packages/core/src/management.ts @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import Context from './context'; +import Context, { isFastRefresh } from './context'; import { setCurrentInstance } from './index'; import type { UnisonPluginClass } from './plugins'; @@ -42,6 +42,9 @@ export type SetupComponent> = (props: ShallowReact * @param name - component name */ export function $unison>(fn: SetupComponent, name?: string) { + if (!isFastRefresh() && typeof window !== "undefined") { + window.__UNISON_REFRESH__ = { root: null }; + } const component = React.forwardRef((props, ref) => { const [instance] = useState(initInstance); const unset = setCurrentInstance(instance); @@ -49,11 +52,11 @@ export function $unison>(fn: SetupComponent, na instance.setupState(); const trackedProps = instance.trackProps({ ...props, ref }); - if (instance.isFastRefresh() && instance.plugins) { - for (const plugin of instance.plugins.values()) plugin.onInstanceFastRefresh?.(instance); + if (isFastRefresh() && instance.plugins) { + for (const plugin of instance.plugins.values()) plugin.onInstanceFastRefresh?.(instance); } - if (!instance.isExecuted() || instance.isFastRefresh()) { + if (!instance.isExecuted() || isFastRefresh()) { instance.children = fn(trackedProps as any); instance.invalidateChildren(); }