I have a react component which gets some resource asynchronously and then subscribes to resource changes.
The problem is that the cleanup function is not in the closure of this resource:
useEffect(() => {
const onResourceChange = () => {
console.log('resource changed');
};
getSomeResource().then(resource => {
resource.subscribe(onResourceChange);
});
return () => {
resource.unsubscribe(onResourceChange); // Error! resource is undefined
}
}, []);
Since using async functions in useEffect is not allowed, what is the best way to unsubscribe from this resource inside useEffect's cleanup function?
I see two "side effects" going on here.
[])[resource])So I
function useResource() {
const [resource, setResource] = useState(undefined)
const onResourceChange = () => console.log('resource changed');
// Get the resource, initially.
useEffect(() => {
getSomeResource(setResource)
}, [])
// When the resource is retrieved (or changed),
// the resource will subscribe and unsubscribe
useEffect(() => {
resource.subscribe(onResourceChange)
return () => resource.unsubscribe(onResourceChange)
}, [resource])
}
// Use it like this
function App() {
useResource()
return <>your elements</>
}
As you can see, the first useEffect is responsible for fetching the "resource" only, while the 2nd useEffect is responsible for un/subscribing the callback.
And check out the deps list in each useEffect (The former is empty [] while the latter depends on [resource])
This is a solution, probably the ugly one... but still a solution :)
useEffect(() => {
const onResourceChange = () => {
console.log('resource changed');
};
let data = {};
getSomeResource().then(resource => {
data.resource = resource;
resource.subscribe(onResourceChange);
});
return () => {
data.resource && data.resource.unsubscribe(onResourceChange); // Error! resource is undefined
};
}, []);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With