mirror of
https://github.com/zoriya/v10.git
synced 2026-08-05 05:37:21 +00:00
fix(react): memoize Provider context value (#1787)
Co-authored-by: James <james@BlainWebDesign.com>
This commit is contained in:
@@ -16,7 +16,7 @@ import type { InferStoreState } from '@videojs/store';
|
||||
import { combine, createStore } from '@videojs/store';
|
||||
import { useStore } from '@videojs/store/react';
|
||||
import type { FC, ReactNode } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { useDestroy } from '../utils/use-destroy';
|
||||
import { Container, PlayerContextProvider, useMedia, usePlayerContext } from './context';
|
||||
@@ -91,11 +91,12 @@ export function createPlayer(config: CreatePlayerConfig<AnyPlayerFeature[]>): Cr
|
||||
return store.attach({ media, container });
|
||||
}, [media, container, store]);
|
||||
|
||||
return (
|
||||
<PlayerContextProvider value={{ store, media, setMedia, container, setContainer, popupGroup }}>
|
||||
{children}
|
||||
</PlayerContextProvider>
|
||||
const value = useMemo(
|
||||
() => ({ store, media, setMedia, container, setContainer, popupGroup }),
|
||||
[store, media, container, popupGroup]
|
||||
);
|
||||
|
||||
return <PlayerContextProvider value={value}>{children}</PlayerContextProvider>;
|
||||
}
|
||||
|
||||
if (__DEV__ && config.displayName) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { act, render, renderHook } from '@testing-library/react';
|
||||
import type { PlayerStore } from '@videojs/core/dom';
|
||||
import { defineSlice } from '@videojs/store';
|
||||
import type { ReactNode } from 'react';
|
||||
import { StrictMode } from 'react';
|
||||
import { StrictMode, useState } from 'react';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { usePlayerContext } from '../context';
|
||||
import { createPlayer } from '../create-player';
|
||||
@@ -188,6 +188,41 @@ describe('createPlayer', () => {
|
||||
|
||||
expect(container.querySelector('[data-testid="child"]')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('provides a stable context value across parent re-renders (fix for #1296)', () => {
|
||||
const { Provider } = createPlayer({ features: [mockSlice] });
|
||||
|
||||
const receivedValues: unknown[] = [];
|
||||
|
||||
function ContextConsumer() {
|
||||
const ctx = usePlayerContext();
|
||||
receivedValues.push(ctx);
|
||||
return null;
|
||||
}
|
||||
|
||||
let forceParentRerender!: () => void;
|
||||
function Parent() {
|
||||
const [, setTick] = useState(0);
|
||||
forceParentRerender = () => setTick((t) => t + 1);
|
||||
return (
|
||||
<Provider>
|
||||
<ContextConsumer />
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
|
||||
render(<Parent />);
|
||||
|
||||
const valueAfterMount = receivedValues[receivedValues.length - 1];
|
||||
|
||||
act(() => forceParentRerender());
|
||||
act(() => forceParentRerender());
|
||||
act(() => forceParentRerender());
|
||||
|
||||
const valueAfterRerenders = receivedValues[receivedValues.length - 1];
|
||||
|
||||
expect(valueAfterRerenders).toBe(valueAfterMount);
|
||||
});
|
||||
});
|
||||
|
||||
describe('usePlayer', () => {
|
||||
|
||||
Reference in New Issue
Block a user