import { useIsomorphicLayoutEffect } from '@fluentui/react-utilities'; import * as React from 'react'; import { unstable_NormalPriority as NormalPriority, unstable_runWithPriority as runWithPriority } from 'scheduler'; const createProvider = (Original)=>{ const Provider = (props)=>{ // Holds an actual "props.value" const valueRef = React.useRef(props.value); // Used to sync context updates and avoid stale values, can be considered as render/effect counter of Provider. const versionRef = React.useRef(0); // A stable object, is used to avoid context updates via mutation of its values. const contextValue = React.useRef(); if (!contextValue.current) { contextValue.current = { value: valueRef, version: versionRef, listeners: [] }; } useIsomorphicLayoutEffect(()=>{ valueRef.current = props.value; versionRef.current += 1; runWithPriority(NormalPriority, ()=>{ contextValue.current.listeners.forEach((listener)=>{ listener([ versionRef.current, props.value ]); }); }); }, [ props.value ]); return React.createElement(Original, { value: contextValue.current }, props.children); }; /* istanbul ignore else */ if (process.env.NODE_ENV !== 'production') { Provider.displayName = 'ContextSelector.Provider'; } return Provider; }; /** * @internal */ export const createContext = (defaultValue)=>{ // eslint-disable-next-line @fluentui/no-context-default-value const context = React.createContext({ value: { current: defaultValue }, version: { current: -1 }, listeners: [] }); context.Provider = createProvider(context.Provider); // We don't support Consumer API delete context.Consumer; return context; };