-
-
Notifications
You must be signed in to change notification settings - Fork 16.7k
Open
Description
The docs suggestion on how to use Reveal with react seem to have a bug.
From: https://revealjs.com/react/
const deckRef = useRef<Reveal.Api | null>(null); // reference to deck reveal instance
useEffect(() => {
// Prevents double initialization in strict mode
if (deckRef.current) return;
deckRef.current = new Reveal(deckDivRef.current!, {
transition: "slide",
// other config options
});
deckRef.current.initialize().then(() => {
// good place for event handlers and plugin setups
});
return () => {
try {
if (deckRef.current) {
deckRef.current.destroy();
deckRef.current = null;
}
} catch (e) {
console.warn("Reveal.js destroy call failed.");
}
};
}, []);
This expressly violates the pitfall described in the React documentation:
https://react.dev/learn/synchronizing-with-effects#dont-use-refs-to-prevent-effects-from-firing
This causes reveal to not unmount properly, the observable bug is that the keyboard bindings from a previous instance remain.
React docs suggest that a cancelation be used instead:
https://react.dev/learn/synchronizing-with-effects#fetching-data
Writing in an abort variable seems to fix the issue along with setting the ref only after initialization.
useEffect(() => {
let abortInitialize = false;
let deck = new Reveal(deckDivRef.current!, {
transition: "slide",
// other config options
});
deck.initialize().then(() => {
if (abortInitialize) {
deck.destroy();
return;
}
// good place for event handlers and plugin setups
deckRef.current = deck;
});
return () => {
try {
abortInitialize = true;
if (deckRef?.current?.isReady()) {
deckRef.current.destroy();
deckRef.current = null;
}
} catch (e) {
console.warn('Reveal.js destroy call failed.');
}
};
}, []);
Related issue:
#3593
bouzidanas and EarlMilkteaPascaltib
Metadata
Metadata
Assignees
Labels
No labels