如何在React Native中侦听子组件中的事件?

时间:2017-11-16 15:59:18

标签: reactjs react-native javascript-events react-navigation eventemitter

我想在我的React Native应用程序中实现从父项到子组件的事件监听器,我使用StackNavigator作为路由器。

如何监听top / parent组件中发生的事件?

6 个答案:

答案 0 :(得分:9)

只需使用React Native' s DeviceEventEmitter。从父组件发出您的活动,如下所示:

DeviceEventEmitter.emit('eventKey', {name:'John', age:23});

并在子组件中监听事件

componentDidMount(){
      //add listener
      this.eventListener = DeviceEventEmitter.addListener('eventKey',this.handleEvent);
}

handleEvent=(event)=>{
 //Do something with event object
}

componentWillUnmount(){
      //remove listener
      this.eventListener.remove();
}

答案 1 :(得分:1)

我一直在研究如何在React Native中将父组件中的事件发送和侦听到子组件,尝试不同的方法后,我认为分享我的工作原理可能会很好。

在您的父组件(在我的例子中为App.js)中,导入EventEmitter lib:

import EventEmitter from 'EventEmitter';

创建事件发射器的变量实例:

export default class App extends Component {

...

  componentWillMount() {
    this.eventEmitter = new EventEmitter();
  }

...

}

然后,当事情发生时会发出事件:

this.eventEmitter.emit('Event-Name', {args});

由于我使用 StackNavigator 作为路由器,我必须将 eventEmitter 变量传递给儿童观点:

const routes = {
  ChildView1: {
    screen: ChildComponent1
  },
  ChildView2: {
    screen: ChildComponent2
  },
  ...
};

const AppNavigator = StackNavigator(
  {
    ...routes,
  },
  {
    initialRouteName: 'ChildView1',
    headerMode: 'none',
  /*
   * Use modal on iOS because the card mode comes from the right,
   * which conflicts with the drawer example gesture
   */
    mode: Platform.OS === 'ios' ? 'modal' : 'card',
  }
);

/* Here is the magic for the children views */

render(){
  return (
    <AppNavigator screenProps={this.eventEmitter} />
  );
}

好的,现在我们已经为子视图提供了事件监听器,让我们在其中一个子组件中调用:

export default class ChildComponent1 extends Component {

  ComponentWillMount(){

    this.eventEmitter = this.props.screenProps;

    this.eventEmitter.addListener('Event-Name', ()=>{

      // Do something

    });

  }

  ...

}

这就是我为子组件完成事件监听器的方式,我希望它可以帮助其他人。如果您有更好的实施,请分享/评论。

答案 2 :(得分:1)

最好的方法是使用Redux作为状态持有者,而不是根据我目前的经验(此问题7个月后)使用EventEmitter,您可以创建变量,该变量将通过组件父子组件传递消息,然后连接组件获取变量(状态)立即发生变化。

我决定使用Rematch,它是Redux的缩小版,并且取得了很好的效果。它迫使我删除所有EventEmitter,并使用调度方法来更新将在连接的组件中更新的变量(状态)。

答案 3 :(得分:1)

最简单的方法:

1)在app.js(初始启动文件)中创建侦听器: 示例:

(new NativeEventEmitter()).addListener('loggedIn',() => {
        setAuth(true);
    });

2)刚从任何孩子身上冒出来:(new NativeEventEmitter()).emit('loggedIn');

希望对某人有用!)

答案 4 :(得分:0)

有一个事件发射器在跟踪事件发生的地点或被侦听的位置时可能会有点麻烦。

就像你通过screenProps={this.eventEmitter}将事件发射器传递给孩子一样(这正是你基本上做的),为什么不传递你的孩子可以用来启动其父母的动作的实际功能。这可能是最有效的做事方式。

添加额外的事件监听器可能不太理想,因为它会在某些时候影响性能。

答案 5 :(得分:0)

我遵循OP使用redux的想法,它对我来说效果很好。这是代码...

actionTypes.js:

export const TRIGGER_REQUEST_SUBMIT = "TRIGGER_REQUEST_SUBMIT";
export const ACKNOWLEDGE_REQUEST_SUBMIT = "ACKNOWLEDGE_REQUEST_SUBMIT";

eventActions.js:

import * as types from "./actionTypes";

export function triggerRequestSubmit() {
  return function(dispatch) {
    dispatch({ type: types.TRIGGER_REQUEST_SUBMIT });
  };
}

export function acknowledgeRequestSubmit() {
  return function(dispatch) {
    dispatch({ type: types.ACKNOWLEDGE_REQUEST_SUBMIT });
  };
}

eventReducer.js:

import * as types from "../actions/actionTypes";
import initialState from "./initialState";

export default function eventReducer(state = initialState.event, action) {
  switch (action.type) {
    case types.TRIGGER_REQUEST_SUBMIT:
      return { ...state, shouldSubmitRequest: true };
    case types.ACKNOWLEDGE_REQUEST_SUBMIT:
      return { ...state, shouldSubmitRequest: false };
    default:
      return state;
  }
}

别忘了在化简器的root-reducer / index.js中注册化简器

initialState.js:

export default {
  event: {
    shouldSubmitRequest: false
  }
};

在子级中的用法(使用redux进行连接并通过状态获取shouldSubmitRequest,通过分派来确认RequestSubmit)

 useEffect(() => {
    if (shouldSubmitRequest) {
      console.log("shouldSubmitRequest triggered in Request");
      acknowledgeRequestSubmit();
    }
  }, [shouldSubmitRequest]);

在父调用中triggerRequestSubmit(); (连接到redux以获取该方法)