【发布时间】:2018-04-30 06:03:00
【问题描述】:
我想在我的 React Native 应用程序中实现从父组件到子组件的事件侦听器,我使用 StackNavigator 作为路由器。
如何监听顶级/父组件中发生的事件?
【问题讨论】:
-
您可以发表问题并自己回答,不要在问题中回答。
标签: reactjs react-native react-navigation dom-events eventemitter
我想在我的 React Native 应用程序中实现从父组件到子组件的事件侦听器,我使用 StackNavigator 作为路由器。
如何监听顶级/父组件中发生的事件?
【问题讨论】:
标签: reactjs react-native react-navigation dom-events eventemitter
只需使用 React Native 的 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();
}
【讨论】:
componentWillUnmount() 事件上的侦听器。这应该被标记为答案
最好的方法不是使用 EventEmitter 以我目前的经验(7 个月后这个问题)是使用 Redux 作为状态持有者,您可以创建将通过组件父子组件传递消息的变量,然后连接获取变量(状态)的组件会立即发生变化。
我决定使用Rematch,它是 Redux 的缩小版,我得到了非常好的结果。它迫使我删除所有的 EventEmitters 并使用调度方法来更新将在连接的组件中更新的变量(状态)。
【讨论】:
我一直在研究如何在 React Native 中从父组件向子组件发出和侦听事件,在尝试了不同的方法后,我认为分享我的工作方式可能会很好。
在您的父组件(在我的例子中为 App.js)中,导入 EventEmitter 库:
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
});
}
...
}
这就是我为子组件完成事件侦听器的方式,希望对其他人有所帮助。如果您有更好的实现,请分享/评论它。
【讨论】:
componentWillReceiveProps 方法。跨度>
最简单的方法:
1) 在您的 app.js 中创建监听器(初始启动文件): 示例:
(new NativeEventEmitter()).addListener('loggedIn',() => {
setAuth(true);
});
2) 只需从任何孩子发出:(new NativeEventEmitter()).emit('loggedIn');
希望它对某人有用!)
【讨论】:
在跟踪事件的来源或被侦听的位置时,使用事件发射器可能会有点混乱。
就像您通过screenProps={this.eventEmitter} 将事件发射器向下传递给孩子一样(这就是您本质上在做的事情),为什么不直接传递您的孩子可以用来在其父级上启动操作的实际函数。这可能是最有反应的做事方式。
添加额外的事件侦听器可能并不理想,因为它会在某些时候影响性能。
【讨论】:
我遵循了 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 中注册 reducer
initialState.js:
export default {
event: {
shouldSubmitRequest: false
}
};
在 child 中的使用(使用 redux 连接并通过 state 获取 shouldSubmitRequest,通过 dispatch 确认RequestSubmit):
useEffect(() => {
if (shouldSubmitRequest) {
console.log("shouldSubmitRequest triggered in Request");
acknowledgeRequestSubmit();
}
}, [shouldSubmitRequest]);
在父调用 triggerRequestSubmit(); (连接到 redux 以获取该方法)
【讨论】: