Reputation: 487
I am trying to call a child function from the right button on the parent navigator.
A basic code example of what I need is as follows:
Main.js
<NavigatorIOS
style={styles.container}
initialRoute={{
title: 'Test',
component: Test,
rightButtonTitle: 'Change String',
onRightButtonPress: () => ***I Want to call miscFunction from here*** ,
passProps: {
FBId: this.state.fbidProp,
favsPage: true
}
}}/>
Test.js
class Test extends React.Component{
constructor(props){
super(props);
this.state = {
variable: 'some string'
};
}
miscFunction(){
this.setState({
variable: 'new string'
};
}
render(){
return(
<Text> {variable} </Text>
)
}
}
Upvotes: 1
Views: 5121
Reputation: 2230
You can use the flux, here is a demo: https://github.com/backslash112/react-native_flux_demo
Upvotes: 0
Reputation: 260
A. In initial component
this.props.navigator.push({
title: 'title',
component: MyComponent,
rightButtonTitle: 'rightButton',
passProps: {
ref: (component) => {this.pushedComponent = component},
},
onRightButtonPress: () => {
// call func
this.pushedComponent && this.pushedComponent.myFunc();
},
});
B. In pushed component
replace onRightButtonPress func in pushed component.
componentDidMount: function() {
// get current route
var route = this.props.navigator.navigationContext.currentRoute;
// update onRightButtonPress func
route.onRightButtonPress = () => {
// call func in pushed component
this.myFunc();
};
// component will not rerender
this.props.navigator.replace(route);
},
Upvotes: 0
Reputation: 16476
This is covered in the following github issue:
https://github.com/facebook/react-native/issues/31
Eric Vicenti comments to describe how Facebook solves this internally:
Currently the best way to do that is to create an
EventEmitter
in the owner of theNavigatorIOS
, then you can pass it down to children usingroute.passProps
. The child can mix inSubscribable.Mixin
and then incomponentDidMount
, you canthis.addListenerOn(this.props.events, 'myRightBtnEvent', this._handleRightBtnPress);
It is clear that this API needs improvement. We are actively working the routing API in Relay, and hopefully react-router, but we want NavigatorIOS to be usable independently. Maybe we should add an event emitter inside the navigator object, so child components can subscribe to various navigator activity:
this.addListenerOn(this.props.navigator.events, 'rightButtonPress', this._handleRightBtnPress);
Here's how this looks in a practical example:
'use strict';
var React = require('react-native');
var EventEmitter = require('EventEmitter');
var Subscribable = require('Subscribable');
var {
AppRegistry,
StyleSheet,
Text,
View,
NavigatorIOS
} = React;
First we pull in all of our requirements including the EventEmitter and Subscribable.
var App = React.createClass({
componentWillMount: function() {
this.eventEmitter = new EventEmitter();
},
onRightButtonPress: function() {
this.eventEmitter.emit('myRightBtnEvent', { someArg: 'argValue' });
},
render: function() {
return <NavigatorIOS
style={styles.container}
initialRoute={{
title: 'Test',
component: Test,
rightButtonTitle: 'Change String',
onRightButtonPress: this.onRightButtonPress,
passProps: {
events: this.eventEmitter
}
}}/>
}
});
In our main top-level component, we create a new EventEmitter (in componentWillMount
) to be available across the component, and then use passProps
to pass it down to the Test
component we specify for the navigator.
We also define a handler for the right button press, which emits a myRightBtnEvent
with some dummy arguments when that button is pressed. Now, in the Test
component:
var Test = React.createClass({
mixins: [Subscribable.Mixin],
getInitialState: function() {
return {
variable: 'original string'
};
},
componentDidMount: function() {
this.addListenerOn(this.props.events, 'myRightBtnEvent', this.miscFunction);
},
miscFunction: function(args){
this.setState({
variable: args.someArg
});
},
render: function(){
return(
<View style={styles.scene}><Text>{this.state.variable}</Text></View>
)
}
});
We add the Subscribable
mixin, and the only other thing we need to do is listen out for the myRightBtnEvent
being fired from the App
component and hook miscFunction
up to it. The miscFunction
will be passed the dummy arguments from the App
press handler so we can use those to set state or perform other actions.
You can see a working version of this on RNPlay:
https://rnplay.org/apps/H5mMNQ
Upvotes: 4