Race condition on <Can />
See original GitHub issueWell, it might not actually be a race condition, as the intended action loses every time, but:
When the <Can /> component’s componentWillReceiveProps
is called with a new Ability
instance, a setState
is called, and then the component’s connectToAbility
is called which ultimately fires off this.recheck()
. https://github.com/stalniy/casl/blob/774457aa43b8f776a9d59542f1462bb191ae0880/packages/casl-react/src/Can.js#L54-L61
That method (this.recheck
) calls this.check
and uses this.props
as params
and this.state.ability
as the ability. However, the call stack is still nested under componentWillReceiveProps
, so the props we’re rechecking against are the old props, and the state is most likely not the (now updated) state (see: https://reactjs.org/docs/react-component.html#setstate)!
The result is that the render method uses this.state.allowed
which was (likely) produced erroneously as described above.
Therefore a good solution to this problem is to move the call to connectToAbility
into the setState
callback:
componentWillReceiveProps(props) {
if (props.ability && this.state.ability !== props.ability) {
this.setState({ ability: props.ability }, () => {
this.connectToAbility(props.ability); // or this.state.ability
});
} else {
this.recheck(props);
}
}
Issue Analytics
- State:
- Created 5 years ago
- Comments:5 (5 by maintainers)
Top GitHub Comments
published in
@casl/react@0.8.1
Thanks for the quick update!