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 0cd2904b23 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 https://github.com/facebook/react-native/pull/7445

Differential Revision: D3274981

fb-gh-sync-id: a1b9d46329f552984e33d11fa0e29ad6da689511
fbshipit-source-id: a1b9d46329f552984e33d11fa0e29ad6da689511
This commit is contained in:
Janic Duplessis 2016-05-08 17:02:33 -07:00 committed by Facebook Github Bot 5
parent b88d9d2380
commit 9aa37e8fb2
1 changed files with 24 additions and 5 deletions

View File

@ -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();
},
});