React Native - pass props from One screen to another screen (using tab navigator to navigate)

时光总嘲笑我的痴心妄想 提交于 2020-05-15 08:37:07

问题


I need to pass data from my HomeScreen to my SecondScreen. There are a ton of examples of how to do this if i'm clicking a button on the HomeScreen to navigate to SecondScreen, but can't find anything showing how to pass to SecondScreen if I'm using a v2 bottom tab navigator to go from HomeScreen to SecondScreen. I've tried screenprops and a couple other methods and spent about 8 hours trying to figure it out but could not get it to work. Any idea how to do this? Please, any hint would be amazing. Here is my code:

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>

    )


    //....

****Please find THINGS I'VE TRIED below:****

HomeScreen.js: when i do this it receives it at first but then passes null

render(){

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

MaintTabNavigator.js: when i do this it receives it at first but then passes null

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

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


HomeStack.path = '';

I've tried like 5 other ways too that I can't even remember at this point. I don't want to have to call my database again in the second screen to get user info. Nobody I know knows react or react native. The React Native documentation at https://reactnavigation.org/docs/en/stack-navigator.html is minimal at best, only showing the below:

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

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

even if you go to the examples in the documentation and search for the word 'screenprop' you will not see any mention of the screen prop feature in either of the examples. All questions that I've seen only address how to pass props on button click which is easy. Is what I'm trying to do possible? I'm sure I'm not the only person using tab navigator who's retrieved data in the homescreen and need to pass it to other screens . Any advice helps. thanks.

ps. Here is my Sign in class that is calling the Home screen:

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;

回答1:


I think you're calling your database in componentDidMount in your HomeScreen component, (I'm right?) and because another component in the same hierarchy needs the same data, you should considerer wrapping this into a new component and do the call to your data in that father component, then you pass the data to all the children that needs it. This is the react way to do things. The state of HomeScreen should not have the data, your data should live in a parent component in a higher hierarchy and pass the data to children as props.

In this way when you create your tabs you can pass the props as the react native docs suggest:

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

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

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

Another solution could be to use a global state management with Redux or something similar.

I hope this helps.

Edit:

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;



回答2:


Use this.props.navigation.navigate.

In your HomeScreen, once you have the data you want to send, then navigate over to SecondScreen like so:

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

To access this in SecondScreen whenever it is navigated to using navigation props, you can use NavigationEvents along with this.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>
  }
}

Edit: For example, with your SignInScreen implementation, to access the props, use:

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



回答3:


I ended up using Redux, it only took me like 100 read throughs and attempts to learn it, but once I learned it it's amazing and simple.




回答4:


This is the basic approach that I am using:

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>
  );
};

Notice that to pass the props to a Screen I am using a child function instead of passing a value to component. The child function can then return the component you want in the syntax you are used to, that has the props available. In this case, the props are the simple name, but you can expand this to handle your state.



来源:https://stackoverflow.com/questions/57186298/react-native-pass-props-from-one-screen-to-another-screen-using-tab-navigator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!