Манипулировать маршрут NavigatorIOS для компонента

Я пытаюсь создать очень простое приложение Todo в React Native. Он состоит из двух видов: один со списком задач, один с полем ввода (для добавления нового). Навигация обеспечивается NavigatorIOS и кнопками на ней (что было бы UIBarButtonItem с UIKit).

В представлении списка есть кнопка "Добавить право" в "Навигаторе", в представлении с текстовым полем, там есть кнопка "Назад" слева и "Готово" справа. Когда вы нажимаете на done, он должен добавить новую задачу с содержимым текстового поля.

Проблема заключается в том, что кнопки и их действия определяются при создании компонента NavigatorIOS, и я не нахожу способ привязать метод, определенный в другом компоненте, как действие кнопки.

В качестве примера, вот мой 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 !');
                            }
                        });
                    }
                }}
            />
        );
    }
}

Я не добавляю сюда два других компонента ItemList и AddTodo, поскольку на нем нет ничего интересного.

Что мне нужно - это способ заставить компоненты взаимодействовать (например, в шаблоне делегирования) с компонентом навигации.

Возможно, это невозможно, или я совершенно ошибаюсь в отношении парадигмы, используемой с React Native, поэтому не стесняйтесь комментировать, если что-то неясно в моем вопросе.

Изменить 05/26

Собственно, команда Facebook знает, что что-то не хватает для обработки этого варианта использования с помощью компонента NavigatorIOS.

Из Эрик Висенти (опубликовано 3 февраля 2015 г.) на проблема на GitHub, который точно охватывает мой вопрос.

В настоящее время лучший способ сделать это - создать EventEmitter у владельца NavigatorIOS, затем вы можете передать его детям, используя route.passProps. Ребенок может перемещаться в Subscribable.Mixin, а затем в componentDidMount, вы можете

this.addListenerOn(this.props.events, 'myRightBtnEvent', this._handleRightBtnPress);

Понятно, что этот API нуждается в улучшении. Мы активно работаем с API маршрутизации в Relay и, надеюсь, реагируем на маршрутизаторы, но мы хотим, чтобы NavigatorIOS можно было использовать независимо. Может быть, мы должны добавить излучателя событий внутри объекта навигатора, чтобы дочерние компоненты могли подписаться на различные действия навигатора:

this.addListenerOn(this.props.navigator.events, 'rightButtonPress', this._handleRightBtnPress);

Ответы

Ответ 1

а. В исходной компоненте

this.props.navigator.push({
    title: 'title',
    component: MyComponent,
    rightButtonTitle: 'rightButton',
    passProps: {
        ref: (component) => {this.pushedComponent = component},
    },
    onRightButtonPress: () => {
        // call func
        this.pushedComponent && this.pushedComponent.myFunc();
    },
});

В. В нажатом компоненте
замените функцию onRightButtonPress в нажатом компоненте.

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