【问题标题】:React Native - pass props from One screen to another screen (using tab navigator to navigate)React Native - 将道具从一个屏幕传递到另一个屏幕(使用选项卡导航器进行导航)
【发布时间】:2019-12-02 19:22:08
【问题描述】:

我需要将数据从我的 HomeScreen 传递到我的 SecondScreen。如果我单击 HomeScreen 上的按钮导航到 SecondScreen,有很多示例说明如何执行此操作,但是如果我使用 v2 底部选项卡导航器,则找不到任何显示如何传递到 SecondScreen 的示例从 HomeScreen 到 SecondScreen。我尝试了 screenprops 和其他几种方法,花了大约 8 个小时试图弄清楚但无法让它工作。知道怎么做吗?拜托,任何提示都会很棒。这是我的代码:

MainTabNavigator.js:

 const config = Platform.select({
  web: { headerMode: 'screen' },
  default: {},
});


const HomeStack = createStackNavigator(
  {
    Home: HomeScreen,

  },
  config

);

HomeStack.navigationOptions = {
  tabBarLabel: 'Home',
  tabBarIcon: ({ focused }) => (
    <MaterialIcons name="home" size={32}  />
  ),
};

HomeStack.path = '';


const SecondStack= createStackNavigator(
  {
    Second: SecondScreen,
  },
  config
);    

SecondStack.navigationOptions = {
  tabBarLabel: 'Second screen stuff',

  tabBarIcon: ({ focused }) => (
    <MaterialIcons name="SecondScreenIcon" size={32}  />
  ),
};

SecondStack.path = '';


const tabNavigator = createBottomTabNavigator({
  HomeStack,
  SecondScreen
});

tabNavigator.path = '';

export default tabNavigator;

HomeScreen.js:

  class HomeScreen extends Component {

  constructor(props){
    super(props);  
  }

 componentDidMount(){

   this.setState({DataFromHomeScreen: 'my data that Im trying to send to SecondScreen'})

  }

//....

SecondScreen.js:

class SecondScreen extends Component {

      constructor(props){
        super(props);  
      }


   render()
   return(     

         <View>{this.props.DataFromHomeScreen}</View>

    )


    //....

****请在下面找到我尝试过的事情:****

HomeScreen.js:当我这样做时,它首先接收它,然后传递 null

render(){

return(
<View>
 //all of my home screen jsx
<SecondScreen screenProps={{DataFromHomeScreen : 'data im trying to pass'}}/>
</View>
)
}

MaintTabNavigator.js:当我这样做时,它首先接收它,然后传递 null

HomeStack.navigationOptions = {
  tabBarLabel: 'Home',
  tabBarIcon: ({ focused }) => (
    <MaterialIcons name="home" size={32}  />
  ),
};

<HomeStack screenProps={{DataFromHomeScreen:'data im trying to pass'}}/>


HomeStack.path = '';

我也尝试了 5 种其他方法,但我现在都不记得了。我不想在第二个屏幕中再次调用我的数据库来获取用户信息。我认识的人都不知道反应或反应本机。 https://reactnavigation.org/docs/en/stack-navigator.html 的 React Native 文档充其量是最少的,仅显示以下内容:

const SomeStack = createStackNavigator({
  // config
});

<SomeStack
  screenProps={/* this prop will get passed to the screen components as this.props.screenProps */}
/>

即使您转到文档中的示例并搜索“screenprop”一词,您也不会在任何一个示例中看到任何关于屏幕道具功能的提及。我看到的所有问题都只解决了如何在按钮点击时传递道具,这很容易。我正在尝试做的事情可能吗?我敢肯定,我不是唯一一个在主屏幕中检索数据并需要将其传递到其他屏幕的选项卡导航器的人。任何建议都有帮助。谢谢。

ps。 这是调用主屏幕的登录类:

class SignInScreen extends React.Component {
static navigationOptions = {
  title: 'Please sign in',
};


render() {
  return (


    <View
    style={styles.container}
    contentContainerStyle={styles.contentContainer}>

    <View>
    <SocialIcon
    title='Continue With Facebook'
    button
    type='facebook'
    iconSize="36"
    onPress={this._signInAsync} 
    />
    </View>

  );
}


_signInAsync = async () => {

    let redirectUrl = AuthSession.getRedirectUrl();
    let result = await AuthSession.startAsync({
      authUrl:
        `https://www.facebook.com/v2.8/dialog/oauth?response_type=token` +
        `&client_id=${FB_APP_ID}` +
        `&redirect_uri=${encodeURIComponent(redirectUrl)}`,
    });      

    var token = result.params.access_token
    await AsyncStorage.setItem('userToken', token);

    await fetch(`https://graph.facebook.com/me?fields=email,name&access_token=${token}`).then((response) => response.json()).then((json) => {

          this.props.navigation.navigate('Home',
          {
              UserName : json.name,
              FBID : json.id,
              email : json.email

          });     


    }) .catch(() => {
       console.log('ERROR GETTING DATA FROM FACEBOOK')
      });

};
 }

export default SignInScreen;

【问题讨论】:

  • 您是在点击SecondScreen 的底部标签按钮时还是通过HomeScreen 中的按钮来传递数据?
  • 我正在从我的数据库中获取主屏幕中的用户数据。理想情况下,一旦我从主屏幕的 fetch 函数中获取数据,我就会将其发送到 SecondScreen 以呈现内容。当我单击 SecondScreen 底部选项卡按钮时,我可以满足于发送数据,但如果第一个选项是不可能的。

标签: reactjs react-native react-native-tabnavigator


【解决方案1】:

我认为您在 HomeScreen 组件中的 componentDidMount 中调用数据库(我是对的?)并且因为同一层次结构中的另一个组件需要相同的数据,您应该考虑将其包装到一个新组件中并执行调用该父组件中的数据,然后将数据传递给所有需要它的子组件。这是react way to do things。 HomeScreen 的状态不应包含数据,您的数据应位于更高层次结构的父组件中,并将数据作为道具传递给子组件。

通过这种方式,当您创建选项卡时,您可以按照 react native 文档的建议传递道具:

import { createBottomTabNavigator, BottomTabBar } from 'react-navigation-tabs';

const TabBarComponent = (props) => (<BottomTabBar {...props} />);

const TabScreens = createBottomTabNavigator(
{
  tabBarComponent: props =>
    <TabBarComponent
      {...props}
      style={{ borderTopColor: '#605F60' }}
    />,
 },
);

另一个解决方案可能是使用 Redux 或类似的全局状态管理。

我希望这会有所帮助。

编辑:

class Home extends React.Component{
 constructor(props){
   super(props);
   this.state = {data: null}
 }
 componentDidMount() {
   //get your props from navigation (your facebook credentials)
   //your call to database
   this.setState({data: yourResponseData});
 }
 render(){
   const TabNavigator = createBottomTabNavigator(
     {
       HomeScreen: props =>
         <HomeScreenStack
           {...this.state.data}
         />,
       SecondStack: props =>
         <SecondStack
           {...this.state.data}
         />,
      },
     );
   return(
     <TabNavigator />
   )
 }
}

const App = createAppContainer(Home);

export default App;

【讨论】:

  • 我使用的是 react-navigation v2,所以我没有 react-navigation-tabs。我从 SignInScreen 调用主屏幕,这是我获取 FB 身份验证信息的地方,一旦我到达 HomeScreen,我将使用来自 SigninScreen 的 FB 身份验证信息调用我的数据库。我明白你所说的需要使用更高阶的组件,但我不确定如何根据我的结构来实现它。
  • Luis,如果有帮助,我在问题的底部添加了我的 SignIn 类
  • 我编辑了我的答案以添加一个实现此结构的 Home 组件。
  • 我尝试了您编辑的答案,并在主屏幕中收到此错误:'不变违规:此导航器缺少导航道具。在 react-navigation 3 中,您必须直接设置您的应用容器。顺便说一句,我只是将 部分放在主屏幕中我的实际视图等中间。
  • 在使用 React Navigation 3 的情况下,您需要一个 App Container,看看我上次的编辑。此代码应位于文件的末尾,首先您需要创建 HomeScreenStack 组件和 SecondStack,这部分代码保持不变.请注意,在此模块中,第一次渲染时数据将为空。
【解决方案2】:

使用this.props.navigation.navigate

在您的HomeScreen 中,一旦您有了要发送的数据,然后导航到SecondScreen,如下所示:

this.props.navigation.navigate('Second', { data: yourData })

要在 SecondScreen 中使用导航道具导航到它时访问它,您可以使用 NavigationEventsthis.props.navigation.getParam

/* your imports */
import { NavigationEvents } from 'react-navigation';

export default class SecondScreen extends React.Component {
  /* your methods and properties */
  render() {
    <View>
      <NavigationEvents
        onDidFocus={() => this.setState({ data: this.props.navigation.getParam('data', {}) })}
      />
      { /* your SecondScreen render code */ }
    </View>
  }
}

编辑:例如,使用您的 SignInScreen 实现,要访问道具,请使用:

const username = this.props.navigation.getParam('UserName', '')
const fbid = this.props.navigation.getParam('FBID', 0)
const email = this.props.navigation.getParam('email', '')

【讨论】:

  • 调用 this.props.navigation.navigate 时会带我到第二个屏幕吗?我不想被带到第二个屏幕,除非我点击底部的标签导航按钮
  • 在这种情况下,我建议将数据保存在AsyncStorage 并在第二个屏幕的componentDidMount 上检索它
  • 它将是一个二维数组,需要从多个屏幕访问它。这只是一个简化的例子
  • Redux 将是采用该路线的最佳方式,但 AsyncStorage 仍然适用于该用例。为了避免每次都在componentDidMount 上重写它,您可以编写一个 HOC (reactjs.org/docs/higher-order-components.html),它将接收目标组件,在挂载时从 AsyncStorage 获取数据,然后将数据作为普通道具传递到目标组件。
【解决方案3】:

这是我使用的基本方法:

import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';

const TestComponent = (props) => {
  return <Text>{`TestComponent: ${props.name}`}</Text>;
};

const Home = () => {
  const Tab = createBottomTabNavigator();

  return (
    <View style={{flex: 1}}>
      <Tab.Navigator>
        <Tab.Screen name="Screen 1">
          {() => <TestComponent name="test 1" />}
        </Tab.Screen>
        <Tab.Screen name="Screen 2">
          {() => <TestComponent name="test 2" />}
        </Tab.Screen>
      </Tab.Navigator>
    </View>
  );
};

请注意,要将道具传递给Screen,我使用的是子函数而不是将值传递给component。然后,子函数可以以您习惯的语法返回您想要的组件,该组件具有可用的道具。在这种情况下,道具是简单的name,但您可以扩展它来处理您的状态。

【讨论】:

    【解决方案4】:

    我最终使用了 Redux,我只花了大约 100 次通读和尝试来学习它,但是一旦我学会了它,它就变得神奇而简单。

    【讨论】:

    • 如果这样能解决用例,能否给作者举个例子?
    猜你喜欢
    • 2017-11-22
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-14
    相关资源
    最近更新 更多