[Navigator] Support the `ref` prop on scene roots

Summary:
Navigator overrides the `ref` prop of scene components so that it can call `onItemRef` and do internal bookkeeping. With callback refs, we can additionally call the original value of the `ref` prop as long as it's a function (that is, string refs are not supported). Note that the `ref` prop is moved to `reactElement.ref` out of `reactElement.props.ref`, which is why this diff accesses `child.ref`.

This diff adds support for callback refs and warns helpfully if a string ref was provided. It should be completely backwards compatible since scenes couldn't have been relying on the `ref` prop before.

cc @ericvicenti

Closes https://github.com/facebook/react-native/pull/1361
Github Author: James Ide <ide@jameside.com>

@public

Test Plan:
 Write a renderScene implementation that puts a callback ref on the root component:
```js
renderScene() {
  return <View ref={component => console.log('yes! this is called')} />;
}
```
This commit is contained in:
James Ide 2015-05-21 10:58:24 -07:00
parent c6670658f4
commit 7f51f9c8a9
1 changed files with 14 additions and 1 deletions

View File

@ -1298,6 +1298,14 @@ var Navigator = React.createClass({
if (i !== this.state.presentedIndex) { if (i !== this.state.presentedIndex) {
disabledSceneStyle = styles.disabledScene; disabledSceneStyle = styles.disabledScene;
} }
var originalRef = child.ref;
if (originalRef != null && typeof originalRef !== 'function') {
console.warn(
'String refs are not supported for navigator scenes. Use a callback ' +
'ref instead. Ignoring ref: ' + originalRef
);
originalRef = null;
}
return ( return (
<View <View
key={this.state.idStack[i]} key={this.state.idStack[i]}
@ -1307,7 +1315,12 @@ var Navigator = React.createClass({
}} }}
style={[styles.baseScene, this.props.sceneStyle, disabledSceneStyle]}> style={[styles.baseScene, this.props.sceneStyle, disabledSceneStyle]}>
{React.cloneElement(child, { {React.cloneElement(child, {
ref: this._handleItemRef.bind(null, this.state.idStack[i], route), ref: component => {
this._handleItemRef(this.state.idStack[i], route, component);
if (originalRef) {
originalRef(component);
}
}
})} })}
</View> </View>
); );