useReward can't find element if it's rendered conditionally
thedevelobear opened this issue · 1 comments
thedevelobear commented
I'm aware of this issue and I'll fix it in the upcoming release. Here's an example of the code that doesn't work at the moment:
const SomeAsyncScreen = () => {
const [ data, setData ] = useState(undefined);
const { reward, isAnimating } = useReward("rewardId", "confetti");
useEffect(() => {
setTimeout(() => {
setData({});
}, 500);
}, []);
if (!data) return "Loading...";
return (
<div className="App">
<span id="rewardId" />
<button disabled={isAnimating} onClick={reward}>
Make it rain!
</button>
</div>
);
};
The problem is that the element is grabbed in useLayoutEffect, which fires synchronously after all DOM mutations. In this case there's no element with an id === "rewardId" on mount.
While I'm working on that, a possible solution would be to bring the target element one level up, or always render the element and make other parts of the screen conditional, like so:
const SomeAsyncScreen = () => {
const [ data, setData ] = useState(undefined);
const { reward, isAnimating } = useReward("rewardId", "confetti");
useEffect(() => {
setTimeout(() => {
setData({});
}, 500);
}, []);
return (
<div className="App">
<span id="rewardId" />
{data && <SomeDataDependentJsx/>}
<button disabled={isAnimating} onClick={reward}>
Make it rain!
</button>
</div>
);
};
thedevelobear commented
This should hopefully work now. Fixed by https://github.com/thedevelobear/react-rewards/releases/tag/v2.0.3