Permalink
Browse files

Make RefreshControl properly controlled by JS

Summary:
There was an issue with the way we made `RefreshControl` a controlled component when react doesn't render synchronously. This fixes the issue by using the same technique used in the commit 0cd2904 for`PickerAndroid`

**Test plan (required)**

Tested normal behaviour and tested that if not setting the `refreshing` prop to `true` during the `onRefresh` callback that the `RefreshControl` stops refreshing immediately. Also made sure that `setNativeProps` is only called if needed when the native refreshing state is not in sync with JS.

Fix #7414
Closes #7445

Differential Revision: D3274981

fb-gh-sync-id: a1b9d46329f552984e33d11fa0e29ad6da689511
fbshipit-source-id: a1b9d46329f552984e33d11fa0e29ad6da689511
  • Loading branch information...
janicduplessis authored and Facebook Github Bot 5 committed May 9, 2016
1 parent b88d9d2 commit 9aa37e8fb2e58a987927356c3562497e4b2b02b6
Showing with 24 additions and 5 deletions.
  1. +24 −5 Libraries/Components/RefreshControl/RefreshControl.js
@@ -86,7 +86,7 @@ const RefreshControl = React.createClass({
/**
* Whether the view should be indicating an active refresh.
*/
refreshing: React.PropTypes.bool,
refreshing: React.PropTypes.bool.isRequired,
/**
* The color of the refresh indicator.
* @platform ios
@@ -124,7 +124,24 @@ const RefreshControl = React.createClass({
size: React.PropTypes.oneOf(RefreshLayoutConsts.SIZE.DEFAULT, RefreshLayoutConsts.SIZE.LARGE),
},
_nativeRef: {},
_nativeRef: (null: any),
_lastNativeRefreshing: false,
componentDidMount() {
this._lastNativeRefreshing = this.props.refreshing;
},
componentDidUpdate(prevProps: {refreshing: boolean}) {
// RefreshControl is a controlled component so if the native refreshing
// value doesn't match the current js refreshing prop update it to
// the js value.
if (this.props.refreshing !== prevProps.refreshing) {
this._lastNativeRefreshing = this.props.refreshing;
} else if (this.props.refreshing !== this._lastNativeRefreshing) {
this._nativeRef.setNativeProps({refreshing: this.props.refreshing});
this._lastNativeRefreshing = this.props.refreshing;
}
},
render() {
return (
@@ -137,11 +154,13 @@ const RefreshControl = React.createClass({
},
_onRefresh() {
this._lastNativeRefreshing = true;
this.props.onRefresh && this.props.onRefresh();
if (this._nativeRef) {
this._nativeRef.setNativeProps({refreshing: this.props.refreshing});
}
// The native component will start refreshing so force an update to
// make sure it stays in sync with the js component.
this.forceUpdate();
},
});

0 comments on commit 9aa37e8

Please sign in to comment.