I'm trying to build a very simple Todo application in React Native. It's composed of two views : one with a list of tasks, one with an input field (to add a new one). Navigation is assured by a NavigatorIOS and buttons on it (which would have been UIBarButtonItem with UIKit).
On the list view, there is a Add right button on Navigator, on the view with the text field, there the back button on the left and a Done one on the right. When clicking on done, it should add a new task with content of text field.
Problem is, buttons and their actions are defined when creating the NavigatorIOS component, and I don't find a way to attach a method defined in another component as a button action.
As an example, here is my NavigatorIOS
class TodoList extends Component {
render() {
return (
<NavigatorIOS
ref="nav"
style={styles.navbar}
initialRoute={{
component: ItemList,
title: 'Todo list',
rightButtonTitle: 'Add',
onRightButtonPress: () => {
this.refs.nav.push({
title: 'Add a new task',
component: AddTodo,
rightButtonTitle: 'Done',
onRightButtonPress: () => {
console.log('done !');
}
});
}
}}
/>
);
}
}
I don't put here my two other components ItemList and AddTodo as there is nothing interesting on it.
What I need is a way to make components communicate (like in delegation pattern) with the navigation component.
Perhaps it's not possible, or I am totally wrong on the paradigm used with React Native, so feel free to comment if something is not clear on my question.
Edit 05/26
Actually, Facebook team is aware that something is missing to handle that use case with NavigatorIOS component.
From Eric Vicenti (posted on February 3 2015) on an issue on GitHub that exactly covers my question.
Currently the best way to do that is to create an
EventEmitterin the owner of theNavigatorIOS, then you can pass it down to children usingroute.passProps. The child can mix inSubscribable.Mixinand 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);
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);
},
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With