refactor(29-01): memoize VuContext and GlobalContext provider values

VuContext:
- Wrap combined value object with useMemo
- vuStore is stable module reference (not a dependency)
- Depends on vuHelpers

GlobalContext:
- Wrap provider value with useMemo
- Dependencies: all state and callback values
- useState setters are stable (not dependencies)

Both contexts now only update consumers when actual data changes,
preventing unnecessary re-renders across the component tree.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Nuwan 2026-03-05 17:52:15 +05:30
parent 6b5b0990bb
commit 566a53fb2b
2 changed files with 30 additions and 17 deletions

View File

@ -1,4 +1,4 @@
import React, { createContext, useState, useCallback, useEffect } from 'react'; import React, { createContext, useState, useCallback, useEffect, useMemo } from 'react';
import useMetronomeState from '../hooks/useMetronomeState'; import useMetronomeState from '../hooks/useMetronomeState';
// Create a global context // Create a global context
@ -77,19 +77,31 @@ export const GlobalProvider = ({ children }) => {
})); }));
}, [handleMetronomeCallback2]); }, [handleMetronomeCallback2]);
// Memoize context value to prevent unnecessary re-renders
// useState setters (setTrackVolumeObject, setGlobalObject) are stable and don't need to be dependencies
const value = useMemo(() => ({
trackVolumeObject,
setTrackVolumeObject,
globalObject,
setGlobalObject,
// Metronome state and functions
metronomeState,
updateMetronomeState,
openMetronome,
closeMetronome,
resetMetronome,
}), [
trackVolumeObject,
globalObject,
metronomeState,
updateMetronomeState,
openMetronome,
closeMetronome,
resetMetronome
]);
return ( return (
<GlobalContext.Provider value={{ <GlobalContext.Provider value={value}>
trackVolumeObject,
setTrackVolumeObject,
globalObject,
setGlobalObject,
// Metronome state and functions
metronomeState,
updateMetronomeState,
openMetronome,
closeMetronome,
resetMetronome,
}}>
{children} {children}
</GlobalContext.Provider> </GlobalContext.Provider>
); );

View File

@ -1,4 +1,4 @@
import React, { createContext, useContext } from 'react'; import React, { createContext, useContext, useMemo } from 'react';
import { vuStore } from '../stores/vuStore'; import { vuStore } from '../stores/vuStore';
import useVuHelpers from '../hooks/useVuHelpers.js'; import useVuHelpers from '../hooks/useVuHelpers.js';
@ -7,11 +7,12 @@ const VuContext = createContext();
export const VuProvider = ({ children }) => { export const VuProvider = ({ children }) => {
const vuHelpers = useVuHelpers(); const vuHelpers = useVuHelpers();
// Combine vuHelpers with vuStore for context value // Memoize context value to prevent unnecessary re-renders
const value = { // vuStore is a stable module-level reference, doesn't need to be a dependency
const value = useMemo(() => ({
...vuHelpers, ...vuHelpers,
vuStore, vuStore,
}; }), [vuHelpers]);
return ( return (
<VuContext.Provider value={value}> <VuContext.Provider value={value}>