WeakRef и FinalizationRegistry: как GC чистит тяжелые ресурсы за вас
WeakRef и FinalizationRegistry: как GC чистит тяжелые ресурсы за вас Вы тянете в React-компонент кэш изображений, WebGL-текстуру или WebAssembly-модуль. Ручная очистка в return useEffect работает только если компонент размонтируется. Если ссылка утекла в замыкание — память забивается. Слабые ссылки решают это без ручного управления. WeakRef — слабая ссылка без блокировки GC WeakRef хранит ссылку на объект, но не мешает сборщику мусора удалить его. Когда объект собран — deref() возвращает undefined. Вы не блокируете память, а только следите, жив ли объект. FinalizationRegistry — колбэк после сборки Регистрируете callback, который вызывается строго после того, как GC собрал объект. Это для освобождения внешних ресурсов: закрыть сокет, отпустить текстуру, отменить подписку. Пример: самовозобновляющийся кэш const cache = new Map<string, WeakRef<object>>(); const registry = new FinalizationRegistry((key: string) => { cache.delete(key); }); function useHeavyData(key: string) { const dataRef = useRef<object | null>(null); useEffect(() => { const cached = cache.get(key)?.deref(); if (cached) { dataRef.current = cached; return; } const newData = computeHeavy(key); cache.set(key, new WeakRef(newData)); registry.register(newData, key); dataRef.current = newData; }, [key]); return dataRef.current; } Типичная ошибка и предупреждение GC не детерминирован — FinalizationRegistry может вызваться через минуту, час или никогда (если браузер упадет). Не полагайтесь на него для критичных по времени очисток. Используйте только для тяжелых объектов: WebAssembly, бинарные данные, WebGL. Для простых JSON или строк — обычный Map с return useEffect, так быстрее и надежнее. Вывод: WeakRef и FinalizationRegistry дают инструмент для автоматической очистки памяти без микроменеджмента в useEffect, но требуют понимания, что GC не мгновенный.