reactjs 在react-navigation 5中传递函数作为参数

vwoqyblh  于 2023-05-28  发布在  React
关注(0)|答案(4)|浏览(170)

**注:**此查询针对react-navigation 5。

在react navigation 4中,我们可以在导航时将函数作为参数传递,但在react navigation 5中,它会抛出一个关于序列化参数的警告。
基本上,我尝试做的是,从父屏幕导航到子屏幕,获取新值并更新父屏幕的状态。
以下是我目前正在实施的方法:

父屏幕

_onSelectCountry = (data) => {
    this.setState(data);
};
.
.
.

<TouchableOpacity
    style={ styles.countrySelector }
    activeOpacity={ 0.7 }
    onPress={ () => Navigation.navigate("CountrySelect",
        {
             onSelect: this._onSelectCountry,
             countryCode: this.state.country_code,
        })
    }
>
.
.
.
</TouchableOpacity>

子屏

_onPress = (country, country_code, calling_code) => {
    const { navigation, route } = this.props;
    navigation.goBack();
    route.params.onSelect({
        country_name: country,
        country_code: country_code,
        calling_code: calling_code
    });
};
vatpfxk5

vatpfxk51#

不建议通过react本机导航参数传递回调,这可能会导致状态冻结(无法正确更新)。这里更好的解决方案是使用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. testEvent")
  };
}, []);
qcuzuvrc

qcuzuvrc2#

您可以使用navigate将数据传递回上一个屏幕,而不是在params中传递onSelect函数:

// `CountrySelect` screen
_onPress = (country, country_code, calling_code) => {
  const { navigation, route } = this.props;
  navigation.navigate('NameOfThePreviousScreen', {
    selection: {
      country_name: country,
      country_code: country_code,
      calling_code: calling_code
    }
  });
};

然后,您可以在第一个屏幕中(在componentDidUpdateuseEffect中)处理此操作:

componentDidUpdate(prevProps) {
  if (prevProps.route.params?.selection !== this.props.route.params?.selection) {
    const result = this.props.route.params?.selection;

    this._onSelectCountry(result);
  }
}
8ehkhllq

8ehkhllq3#

有一种情况,你必须把一个函数作为参数传递给屏幕。
例如,您有第二个(独立的)NavigationContainer,它在Modal中呈现,当您在某个屏幕中按Done时,您必须隐藏(关闭)Modal组件。
目前我看到的唯一解决方案是将所有内容都放在Context.Provider中,然后在屏幕中使用Context.Consumer来调用Modal的示例方法hide()

cclgggtu

cclgggtu4#

它抛出警告的部分原因是因为在导航参数中传递函数会使地址栏变得混乱,并且当将应用程序作为启用链接的react-native-web的Web应用程序运行时会导致错误。然而,你是对的,如果你只是为移动设备开发,它会工作得很好,只是风格不好(请参阅https://reactnavigation.org/docs/params/#what-should-be-in-params)。

  • 请注意,当myFunc通过参数传递时,只是一堆无法读取的垃圾https://localhost:19006/My%20App?dataId = 20&myFunc = function%20onGoBack%28%29%20%7B%0A%20%20%20%20%20%20%20% 20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20@this2.fetchAssets%280%2C%20_this2.state.searchTerm%2C%20_this2.state.selectedFilterOption%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D

<NavigationContainer linking ={{enabled:真实的

  • 当您尝试使用导航参数中的函数刷新页面时会发生此错误TypeError:_this2.props.route.params.myFunc不是函数

您可以使用DeviceEventEmitter之类的库来避免这种情况,但这很容易做到,无需添加另一个冗余库。

// In App.js
import React, { Component } from 'react'
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import Facilities from './pages/facilities';
import FacilityDetails from './pages/facility-details';

export default class App extends Component {
  pageData = {};

  state = {

  }

  render() {
    const Stack = createNativeStackNavigator();

    return (
      // Setting linking prop to enabled makes the screen and any props encoded in the browser URL on web.
      <NavigationContainer
        linking={{ enabled: true }} 
      >
        <Stack.Navigator >
          <Stack.Screen name='Facilities'>
            {(props) => <Facilities {...props} setPageData={this.setPageData} />}
          </Stack.Screen>
          <Stack.Screen name='Facility Details'>
            {(props) => <FacilityDetails {...props} getPageData={this.getPageData} />}
          </Stack.Screen>
        </Stack.Navigator>
      </NavigationContainer>
    );
  }

  setPageData = (dataName, data) => {
    this.pageData[dataName] = data;
  }

  getPageData = () => {
    return this.pageData;
  }
}

因此,如果我们想将facilities.js中的函数传递给facility-details.js并调用它,我们只需要在导航之前调用facilities中的setPageData,然后在facility details中调用getPageData:

// In facilities.js
this.props.setPageData('myFunc', this.myFunc);
this.props.navigation.navigate('Facility Details');

// In facility-details.js
this.props.getPageData().myFunc();

相关问题