react-navigation:是否可以将回调传递给 children (e.g.changeHandler)?
react-navigation: Is it possible to pass a callback to children (e.g.changeHandler)?
我一直在尝试的是将回调传递到屏幕。
这是我的实验摘录...
export default class Test extends React.Component {
constructor(props) {
super(props);
};
handleOnPress(data){
//How do we pass this callback to "Home" or "Sub"?
}
render() {
const Navigator = StackNavigator({
Home: {screen: Home},
Sub: {screen: Sub}
});
let data = {blah:"blah blah"};
return (<Navigator screenProps={data} />);
}
}
在这个例子中,我可以在Home
和Sub
中得到this.props.screenProps.blah
。
我以为能够传递 prop 也意味着能够传递回调,但我觉得我不对。
有人遇到过这个问题吗?
如有任何建议,我们将不胜感激。
如果您只想将回调传递给 child,您也可以在渲染中指定为道具:
<Navigator callback={this.handleOnPress} {/*And any other props you want to pass*/} />
然后在您的 Home
或 Sub
class 中触发您可能期望的回调
class Home extends React.Component {
//...
somefunction = () => {
this.props.callback();
}
}
这就是我现在在代码中使用的内容。
尽管如果您只想将其传递给 Home
或 Sub
之一,这可能是您的答案:https://github.com/react-community/react-navigation/issues/935
const mapNavigationStateParamsToProps = (SomeComponent) => {
return class extends Component {
static navigationOptions = SomeComponent.navigationOptions; // better use hoist-non-react-statics
render() {
const {navigation: {state: {params}}} = this.props
return <SomeComponent {...params} {...this.props} />
}
}
}
编辑:在我的例子中,我的处理程序是一个箭头函数,如下所示:
handleOnPress = (data) => {
//Do something here
}
这样我就不用处理.bind()
s
OP 的最终解决方案:
看起来 StackNavigator
需要将道具作为 screenProps
传递,因此渲染函数变为:
render() {
const Navigator = StackNavigator({
Home: {screen: Home},
Sub: {screen: Sub}
});
let props = {
data: "data",
handleOnPress: () => this.handleOnPress()
};
return (<Navigator screenProps={props} />);
}
不推荐通过 react native 导航参数传递回调,这可能会导致状态冻结(无法正确更新)。这里更好的解决方案是使用 EventEmitter,因此回调保留在 Screen1 中,并在 Screen2 发出事件时调用。
屏幕 1 代码:
import DeviceEventEmitter from "react-native"
DeviceEventEmitter.addListener("event.testEvent", (eventData) =>
callbackYouWantedToPass(eventData)));
屏幕 2 代码:
import DeviceEventEmitter from "react-native"
DeviceEventEmitter.emit("event.testEvent", {eventData});
useEffect(() => {
return () => {
DeviceEventEmitter.removeAllListeners("event.mapMarkerSelected")
};
}, []);
我一直在尝试的是将回调传递到屏幕。
这是我的实验摘录...
export default class Test extends React.Component {
constructor(props) {
super(props);
};
handleOnPress(data){
//How do we pass this callback to "Home" or "Sub"?
}
render() {
const Navigator = StackNavigator({
Home: {screen: Home},
Sub: {screen: Sub}
});
let data = {blah:"blah blah"};
return (<Navigator screenProps={data} />);
}
}
在这个例子中,我可以在Home
和Sub
中得到this.props.screenProps.blah
。
我以为能够传递 prop 也意味着能够传递回调,但我觉得我不对。
有人遇到过这个问题吗?
如有任何建议,我们将不胜感激。
如果您只想将回调传递给 child,您也可以在渲染中指定为道具:
<Navigator callback={this.handleOnPress} {/*And any other props you want to pass*/} />
然后在您的 Home
或 Sub
class 中触发您可能期望的回调
class Home extends React.Component {
//...
somefunction = () => {
this.props.callback();
}
}
这就是我现在在代码中使用的内容。
尽管如果您只想将其传递给 Home
或 Sub
之一,这可能是您的答案:https://github.com/react-community/react-navigation/issues/935
const mapNavigationStateParamsToProps = (SomeComponent) => {
return class extends Component {
static navigationOptions = SomeComponent.navigationOptions; // better use hoist-non-react-statics
render() {
const {navigation: {state: {params}}} = this.props
return <SomeComponent {...params} {...this.props} />
}
}
}
编辑:在我的例子中,我的处理程序是一个箭头函数,如下所示:
handleOnPress = (data) => {
//Do something here
}
这样我就不用处理.bind()
s
OP 的最终解决方案:
看起来 StackNavigator
需要将道具作为 screenProps
传递,因此渲染函数变为:
render() {
const Navigator = StackNavigator({
Home: {screen: Home},
Sub: {screen: Sub}
});
let props = {
data: "data",
handleOnPress: () => this.handleOnPress()
};
return (<Navigator screenProps={props} />);
}
不推荐通过 react native 导航参数传递回调,这可能会导致状态冻结(无法正确更新)。这里更好的解决方案是使用 EventEmitter,因此回调保留在 Screen1 中,并在 Screen2 发出事件时调用。
屏幕 1 代码:
import DeviceEventEmitter from "react-native"
DeviceEventEmitter.addListener("event.testEvent", (eventData) =>
callbackYouWantedToPass(eventData)));
屏幕 2 代码:
import DeviceEventEmitter from "react-native"
DeviceEventEmitter.emit("event.testEvent", {eventData});
useEffect(() => {
return () => {
DeviceEventEmitter.removeAllListeners("event.mapMarkerSelected")
};
}, []);