Coder Social home page Coder Social logo

Comments (14)

VBarzionov avatar VBarzionov commented on May 2, 2024 23

I need to pass same "userId" param to all Tabs inside Tab.Navigator
Doc says there is no "dangerouslyGetParent().getParams" in React Navigation 5 any more.
However it is totally unclear how to share/access same "nav-param" for all Tabs inside TabNavigator now.
One solution is using external storage (react-context/redux/other).

I found following solution/workaround. Hope it helps somebody.

  <Stack.Screen name="Settings" >
    { (props) => (
      <Tab.Navigator>
        <Tab.Screen name="Tab1" component={ Tab1 } 
          initialParams={ props.route.params }  // <- pass params from root navigator
        />
        <Tab.Screen name="Tab2" component={ Tab2 } 
          initialParams={ props.route.params } 
        />
      </Tab.Navigator>
      )}
  </Stack.Screen>

Navigation params pass from root stack-navigator to all Tabs

from rfcs.

brentvatne avatar brentvatne commented on May 2, 2024 9

this causes a lot of confusion - react-navigation/react-navigation#4811

we should document this.props.navigation.dangerouslyGetParent().getParam(...) as a way to get the params from the parent, or provide a method that gets params from the parent without the word dangerously maybe...

from rfcs.

liuqiang1357 avatar liuqiang1357 commented on May 2, 2024 3

I don't think the getParentParam is necessary, because if we passed params to child navigator, we can reference the params by dangerouslyGetParent().getParams in the child screen, and we also can wrap the navigator to decide how to use the params for all the child screen (see pull request below).

But at first we should let the child navigator to receive params. There is some issue in current version and I have made a pull request #4306 .

from rfcs.

Titozzz avatar Titozzz commented on May 2, 2024 2

I have a use case where It would be helpful to me that any screen / navigator under a certain navigator gets a common param, and I really believed this would be the default behavior (passing down all params with the child always having priority when param names conflict).

I will use a workaround by extending navigator and using react context in the meantime 😄

from rfcs.

Titozzz avatar Titozzz commented on May 2, 2024 2

Using react context wrapping my navigator is exactly what I did, sorry I did not give more details in my above message 😄. And once hooks land in stable react-native it'll get even cleaner to use.

from rfcs.

mtnt avatar mtnt commented on May 2, 2024

Since it is react-navigation I guess params should be converted to props. It should be passed to a target component only. All further props-params manipulations in the component is up to a developer.

Since I believe the navigator should be able to made as a HOC (without any scene changed inside itself), params should be available to be taken in navigationOptions, for example, for a header configuration.

from rfcs.

brentvatne avatar brentvatne commented on May 2, 2024

@mtnt - they are props. this.props.navigation.state.params. that's not really what this issue is about though. the question here is how we should deal with params when they are passed into a navigator, so if you navigate to a screen that is just a react component vs a screen that is a navigator, would params be passed through to the screen rendered by the navigator or not?

from rfcs.

mtnt avatar mtnt commented on May 2, 2024

@brentvatne I meant first level props - this.props.param0, but ok, I`ll open another one issue for this point.

About your comment. As I already said, I think params should be passed into a navigation target screen only (without passing through). What to do with it further is the screen responsibility.

from rfcs.

slorber avatar slorber commented on May 2, 2024

Hi @Titozzz

If you need to build some kind of multiscreen stateful wizzard you can share state across those screens by wrapping the navigator.

MyStatelessStackNavigator = createStackNavigator({})

// Forward the prop
MyStatefulStackNavigator = ({navigation}) => (
   <MyStateProvider>
      <SomeFancyWizzardStepHeader/>
      <MyStatelessStackNavigator navigation={navigation}/>
   </MyStateProvider>
);

// Very important otherwise MyStatefulStackNavigator is not considered as a navigator
MyStatefulStackNavigator.router =  MyStatelessStackNavigator.router; 

export default MyStatefulStackNavigator;

This is a common pattern where you just wrap a navigator inside custom one to enhance it.
More infos here: https://reactnavigation.org/docs/en/custom-navigators.html

Unlike global state based solutions, this one will actually reset its state when you navigate away from this navigator, which makes it more suitable for transcient state like multi-screen forms/wizzards... I think we should do a better job at documenting this kind of patterns with react-navigation. Will probably write a blog about it soon.

Note you might be tempted to try to use "screenProps" here but actually this should only be used on root app container, and after discussing with Satya last year he suggested using context is the way to go for this kind of usecase, and maybe screenProps would be deprecated some day.

Note if you are looking for an easy to use state provider to make your stack navigation stateful, I think unstated is a very decent option and anyone knowing React will understand how to build features with this very easily. Once it's setup you almost get no learning curve. Only difference is setState being async (which imho is a nice addition).

And if you don't need a stateful wrapper, you can still use the trick above and add a simple React context to propagate a static value to all subscreens.

from rfcs.

bhave-abhay avatar bhave-abhay commented on May 2, 2024

I was struggling with the same, and after almost a week of frustration finally used context and got what I wanted, demonstrated in react-navigation/react-navigation#5646

I think the mention of possibilities with the use of cotext api (though it is in parent platform i.e. react) in react-navigation documentation would help a lot.

Should we / I open an issue for this on documentation site repo?

from rfcs.

brentvatne avatar brentvatne commented on May 2, 2024

@bhave-abhay - a docs page for that could be really great! you would probably be a great person to write it given the experience you've had, can you open a pr for it?

from rfcs.

SaeedZhiany avatar SaeedZhiany commented on May 2, 2024

@brentvatne
Let's assume a routing like below:

DrawerNavigator:
|______ StackNavigator
          |______ Screen 1
          |______ TabNavigator
                    |_______ Tab 1 <--- initial route
                    |_______ Tab 2
                    |_______ Tab 3

One scenario for the routing is an app that shows a list of items in Screen 1 and shows an item's detail when the user pressed on the item. because of the massive amount of information, the developer decides to show the information in three tabs (price tab, technical info, and contact tab), So the tabs are related, also, assume that the developer should fetch the data by sending 3 different requests to a server (in the scenario I'm thinking about the tabs are able to work completely separated from each other, in other words, although the tabs are showing information of the same Item all of their processes are isolated from each other). in the other hand, the server may expect an ItemId and some other parameters in the request for each tab.

in the current implementation, we should pass all parameters to the TabNavigator and extract the required params in each tab using this.props.navigation.state.params in Tab 1 and this.props.navigation.dangerouslyGetParent().getParams in the other Tabs. it has two cons in my opinion:

  1. If the developer wants to change the order of the tabs, he/she must change the code to retrieve params, because of two different access way to the parameters.
  2. Developers like me may like to convert params to component props to easily accessible in a consistent way (by using something like below)
Tab 1: {
    screen: (props) => (<ScreenWrapper component={ItemOverviewScreen} params={props}/>)
}

Class ScreenWrapper {
    public render() {
        const Component = this.props.component;
        return (
            <Component {...this.props.params}/>
        );
    }
}

Class ItemOverviewScreen {
    // work with props without any concern and knowledge about routings parameter passing
}

Not passing down the params causes we lose the above ability in tab navigators at least.

  1. For some reason, Let assume that the app's routing is changed like below:
DrawerNavigator:
|______ StackNavigator
          |______ Screen 1
          |______ TabNavigator
                    |_______ Tab 1 <--- initial route
                    |_______ Tab 2
                    |_______ Tab 3
          |______ Tab 3 <--- the same screen used in above Tab 3

the developer must check both this.props.navigation.state.params and this.props.navigation.dangerouslyGetParent().getParams to cover both routing in one place.

My suggestion
Passing the params of each tab by wrapping them into an object with a key of the corresponding Tab routing name. I mean something like below:

The developer doing navigate to Tab Navigator:

NavigationAction.navigate ({
    routeName: TabNavigator,
    params: {
        Tab 1: {
            // params of Tab 1
        },
        Tab 2: {
            // params of Tab 2
        },
        Tab 3: {
            // params of Tab 3
        },
    }
});

the library should pass only the corresponding params to each Tab in the screen: (props) => ....
probably we can extend the suggestion for other Navigators include nested ones.

from rfcs.

TheEhsanSarshar avatar TheEhsanSarshar commented on May 2, 2024

@brentvatne getParam is undefined

from rfcs.

imavipatel avatar imavipatel commented on May 2, 2024

I need to pass same "userId" param to all Tabs inside Tab.Navigator
Doc says there is no "dangerouslyGetParent().getParams" in React Navigation 5 any more.
However it is totally unclear how to share/access same "nav-param" for all Tabs inside TabNavigator now.
One solution is using external storage (react-context/redux/other).

I found following solution/workaround. Hope it helps somebody.

  <Stack.Screen name="Settings" >
    { (props) => (
      <Tab.Navigator>
        <Tab.Screen name="Tab1" component={ Tab1 } 
          initialParams={ props.route.params }  // <- pass params from root navigator
        />
        <Tab.Screen name="Tab2" component={ Tab2 } 
          initialParams={ props.route.params } 
        />
      </Tab.Navigator>
      )}
  </Stack.Screen>

Navigation params pass from root stack-navigator to all Tabs

thank you so much for this. I was trying to solve this problem from last 2 days luckily i reached here

from rfcs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.