Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Stash callbacks passed to one-time initializers in a ref
When a callback is consumed by something built once (e.g. inside a useMemo factory with an incomplete dependency array), store it in a ref and call via ref.current to avoid a stale closure.
Bad example
| 1 | const editor = useMemo( |
| 2 | () => |
| 3 | createEditor({ |
| 4 | extensions: [ |
| 5 | createExtensions({ onGenerateCaption }), |
| 6 | ], |
| 7 | }), |
| 8 | [], // onGenerateCaption intentionally omitted |
| 9 | ); |
Explanation (EN)
onGenerateCaption is captured by the closure at creation time and is never updated, because it isn't in the dependency array (and can't be, without recreating the whole editor). If the callback later depends on fresher props or state, the editor keeps calling the stale version.
Objašnjenje (HR)
onGenerateCaption je uhvacen u closure u trenutku kreiranja i nikad se ne azurira jer nije u dependency arrayu (a ne moze ni biti, bez ponovnog kreiranja cijelog editora). Ako callback kasnije ovisi o svjezijim propsima ili stanju, editor i dalje poziva zastarjelu verziju.
Good example
| 1 | const onGenerateCaptionRef = useRef(onGenerateCaption); |
| 2 | useEffect(() => { |
| 3 | onGenerateCaptionRef.current = onGenerateCaption; |
| 4 | }, [onGenerateCaption]); |
| 5 |
|
| 6 | const editor = useMemo( |
| 7 | () => |
| 8 | createEditor({ |
| 9 | extensions: [ |
| 10 | createExtensions({ |
| 11 | onGenerateCaption: (...args) => onGenerateCaptionRef.current?.(...args), |
| 12 | }), |
| 13 | ], |
| 14 | }), |
| 15 | [], |
| 16 | ); |
Explanation (EN)
The initializer captures a stable wrapper that always forwards to the ref's current value, so the editor can be created once while still calling the latest callback passed in from props.
Objašnjenje (HR)
Inicijalizator hvata stabilan wrapper koji uvijek prosljeduje trenutnu vrijednost iz refa, tako da se editor moze kreirati jednom, a ipak uvijek poziva najnoviji callback proslijeden kroz propse.
Notes (EN)
This is the same pattern the codebase already used for onEditorKeyDownRef, reuse it consistently for any callback fed into a one-time editor or factory setup.
Bilješke (HR)
Ovo je isti obrazac koji se vec koristi za onEditorKeyDownRef, primijeni ga dosljedno za svaki callback koji se proslijeduje u jednokratnu inicijalizaciju editora ili tvornice.