diff --git a/src/jsx/dom/index.test.tsx b/src/jsx/dom/index.test.tsx
index 03e552fe8..23a4f82eb 100644
--- a/src/jsx/dom/index.test.tsx
+++ b/src/jsx/dom/index.test.tsx
@@ -19,6 +19,8 @@ import DefaultExport, {
cloneElement,
cloneElement as cloneElementForDom,
createElement as createElementForDom,
+ createContext,
+ useContext,
createPortal,
flushSync,
isValidElement,
@@ -1492,6 +1494,36 @@ describe('DOM', () => {
expect(root.innerHTML).toBe('
')
expect(renderCount).toBe(2)
})
+
+ it('should not return memoized result when context is not changed', async () => {
+ const Context = createContext<[number, (arg: number | ((value: number) => number)) => void]>([
+ 0,
+ () => {},
+ ])
+ const Container: FC<{ children: Child }> = ({ children }) => {
+ const [count, setCount] = useState(0)
+ return {children}
+ }
+ const Content = () => {
+ const [count, setCount] = useContext(Context)
+ return (
+ <>
+ {count}
+
+ >
+ )
+ }
+ const app = (
+
+
+
+ )
+ render(app, root)
+ expect(root.innerHTML).toBe('0')
+ root.querySelector('button')?.click()
+ await Promise.resolve()
+ expect(root.innerHTML).toBe('1')
+ })
})
describe('useRef', async () => {
diff --git a/src/jsx/dom/render.ts b/src/jsx/dom/render.ts
index 2297c3af3..ecaaaa626 100644
--- a/src/jsx/dom/render.ts
+++ b/src/jsx/dom/render.ts
@@ -451,6 +451,16 @@ const applyNodeObject = (node: NodeObject, container: Container, isNew: boolean)
}
}
+const isSameContext = (
+ oldContexts: LocalJSXContexts,
+ newContexts: NonNullable
+): boolean =>
+ !!(
+ oldContexts &&
+ oldContexts.length === newContexts.length &&
+ oldContexts.every((ctx, i) => ctx[1] === newContexts[i][1])
+ )
+
const fallbackUpdateFnArrayMap: WeakMap<
NodeObject,
Array<() => Promise>
@@ -525,13 +535,15 @@ export const build = (context: Context, node: NodeObject, children?: Child[]): v
oldChild.props = child.props
oldChild.f ||= child.f || node.f
if (typeof child.tag === 'function') {
+ const oldContexts = oldChild[DOM_STASH][2]
oldChild[DOM_STASH][2] = child[DOM_STASH][2] || []
oldChild[DOM_STASH][3] = child[DOM_STASH][3]
if (
!oldChild.f &&
((oldChild.o || oldChild) === child.o || // The code generated by the react compiler is memoized under this condition.
- (oldChild.tag as MemorableFC)[DOM_MEMO]?.(pP, oldChild.props)) // The `memo` function is memoized under this condition.
+ (oldChild.tag as MemorableFC)[DOM_MEMO]?.(pP, oldChild.props)) && // The `memo` function is memoized under this condition.
+ isSameContext(oldContexts, oldChild[DOM_STASH][2])
) {
oldChild.s = true
}