2015-07-02 2 views
1

Я пытаюсь вызвать дочернюю функцию справа от родительского навигатора.React Native - вызов функции дочернего элемента из NavigatorIOS

Основной код пример того, что мне нужно, это выглядит следующим образом:

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

ответ

4

Это описано в следующем GitHub выпуске:

https://github.com/facebook/react-native/issues/31

Эрик Висенти комментарии, чтобы описать, как Facebook решает эту проблему внутренне:

Currently the best way to do that is to create an EventEmitter in the owner of the NavigatorIOS , then you can pass it down to children using route.passProps . The child can mix in Subscribable.Mixin and then in componentDidMount , you can

this.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); 

Вот как это выглядит в качестве практического примера:

'use strict'; 

var React = require('react-native'); 
var EventEmitter = require('EventEmitter'); 
var Subscribable = require('Subscribable'); 

var { 
    AppRegistry, 
    StyleSheet, 
    Text, 
    View, 
    NavigatorIOS 
} = React; 

Сначала мы тянем во всех наших требований, в том числе EventEmitter и 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 
        } 
       }}/> 
    } 
}); 

В нашей основной компонент верхнего уровня, мы создаем новый EventEmitter (в componentWillMount) должны быть доступны через компонент, а затем использовать passProps, чтобы передать ее в Test компоненте мы указываем для навигатора.

Мы также определяем обработчик для нажатия правой кнопки, который испускает myRightBtnEvent с некоторыми фиктивными аргументами при нажатии этой кнопки. Теперь, в Test компонента:

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

Добавляем Subscribable подмешать, и единственное, что нам нужно сделать, это слушать вне для myRightBtnEvent увольняют из App компонента и подключить miscFunction к нему. miscFunction будет передан фиктивные аргументы из обработчика печати App, поэтому мы можем использовать их для установки состояния или выполнения других действий.

Вы можете увидеть рабочую версию этого на RNPlay:

https://rnplay.org/apps/H5mMNQ

+0

Спасибо за ответ. Я все еще немного любитель, когда речь заходит о реакции на родной язык. Является ли EventEmitter частью реакции-родной уже или мне нужно добавить его? также не знакомы с Subscribable.Mixin –

+0

EventEmitter поставляется с React Native, а Subscribable использует его. Если вы выполните поиск подписок на React Native github, вы увидите несколько примеров, но я попытаюсь сформулировать свой ответ, когда у меня будет больше времени. –

+0

Добавлен полный пример. –

0

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

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. В толкнул компонент
заменить onRightButtonPress FUNC в толкаемом компонента.

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); 
}, 
Смежные вопросы