【问题标题】:React Native - Call Function of child from NavigatorIOSReact Native - 从 NavigatorIOS 调用子函数
【发布时间】:2015-07-02 06:48:14
【问题描述】:

我正在尝试从父导航器上的右键调用子函数。

我需要的基本代码示例如下:

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

【问题讨论】:

    标签: reactjs react-native


    【解决方案1】:

    这在以下 github 问题中有所涉及:

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

    Eric Vicenti 描述 Facebook 如何在内部解决这个问题:

    目前最好的方法是在NavigatorIOS 的所有者中创建一个EventEmitter,然后您可以使用route.passProps 将其传递给孩子。孩子可以混入Subscribable.Mixin再混入componentDidMount,就可以了

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

    很明显,这个 API 需要改进。我们正在积极使用 Relay 中的路由 API,并希望使用 react-router,但我们希望 NavigatorIOS 能够独立使用。也许我们应该在 navigator 对象中添加一个事件发射器,以便子组件可以订阅各种 navigator 活动:

    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 mixin,我们唯一需要做的另一件事就是监听myRightBtnEventApp 组件触发并将miscFunction 挂接到它。 miscFunction 将从 App 按下处理程序传递虚拟参数,以便我们可以使用它们来设置状态或执行其他操作。

    你可以在 RNPlay 上看到这个的工作版本:

    https://rnplay.org/apps/H5mMNQ

    【讨论】:

    • 感谢您的回复。在反应原生方面,我仍然有点业余。 EventEmitter 是 react-native 的一部分还是我需要添加它?也不熟悉 Subscribable.Mixin
    • EventEmitter 随 React Native 一起提供,Subscribable 也利用了它。如果您在 React Native github 上搜索 Subscribable,您会看到一些示例,但当我有更多时间时,我会尝试充实我的答案。
    • 添加了一个完整的例子。
    • 我正在努力让这个示例与 es6 一起使用。我不断收到此错误 Uncaught TypeError: this.addListenerOn is not a function
    • 哦,es6 没有 mixins,所以我也不确定。
    【解决方案2】:

    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 函数。

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

    【讨论】:

      【解决方案3】:

      您可以使用flux,这是一个演示:https://github.com/backslash112/react-native_flux_demo

      【讨论】:

        猜你喜欢
        • 2015-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-26
        • 2017-09-04
        相关资源
        最近更新 更多