Last active
March 19, 2018 10:59
-
-
Save bvaughn/e7602e7751908fe3b1d0e66087d8b869 to your computer and use it in GitHub Desktop.
Allowing child components to request side effects in an async-way?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Example extends React.Component { | |
// Store the has-been-requested flag in state, since side-effects are tied to a particular render. | |
// Since this value is managed by React, this will make sure it gets set/reset correctly. | |
state = { | |
sideEffectData: { | |
hasBeenRequested: false, | |
} | |
}; | |
componentDidMount() { | |
this.maybeApplySideEffects(); | |
} | |
componentDidUpdate(prevProps, prevState) { | |
this.maybeApplySideEffects(); | |
} | |
render() { | |
return this.props.children(this.requestSideEffect); | |
} | |
requestSideEffect = () => { | |
if (this.state.sideEffectData.hasBeenRequested) { | |
console.warn('Side effect has been requested multiple times during a single render pass'); | |
} | |
// This value does not impact render, so it's okay to mutate it. | |
// We'll check it during the commit phase to conditionally apply a side effect. | |
this.state.sideEffectData.hasBeenRequested = true; | |
} | |
maybeApplySideEffects() { | |
if (this.state.sideEffectData.hasBeenRequested) { | |
this.state.sideEffectData.hasBeenRequested = false; | |
// Process phase side-effects now. | |
// They're safe, since we're in the commit phase. | |
} | |
} | |
} |
This gist should be disregarded as a silly, late-night idea.
Another potential source of problem would be if a side effect is requested by a child that was rendered previously, after a new child has been rendered (but not yet committed).
As Sebastian points out, a child requesting a side-effect during render is a side-effect and so is not an async-safe practice by definition.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The above gist has (at least one) glaring problem: Side effects won't get applied if the callback is called outside of the render phase. 😄