Skip to content
This repository has been archived by the owner on May 8, 2019. It is now read-only.

Tab navigator experiments #19

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

Conversation

vnovick
Copy link
Collaborator

@vnovick vnovick commented Dec 30, 2018

  • Nested Tab Navigator example
  • Experiments with navigations
  • Changes for all reactElement return types to reactClass

package.json Show resolved Hide resolved
navigationOptions: screenOptions,
};

module NavigationProp = {
[@bs.send] external navigate: string => unit = "navigate";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we pass the Variant to the navigate function, or not?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah in the end we need to pass a variant. We don't want to use string. This is just an experiment. This is not working yet. navigation is WIP.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, would be great to add a comment there to know what's going there

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case we don't. "NavigationProp" module is a binding to React Navigation's "navigation" that operates on strings and is not aware of ReasonML variant.

This is going to be super similar to

module NavigationProp = {
type t;
module State = {
type t;
[@bs.get] external getParams: t => option(routeProps) = "params";
};
[@bs.send] external push: (t, string, routeProps) => unit = "push";
[@bs.get "state"] external getState: t => State.t = "";
let getParams = t => getState(t) |> State.getParams;
};
and once we complete both, I think there's an opportunity to extract a common part.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let tabs =
Config.order
|> List.map(tab => {
let (tabname, screen, screenOptionsConfig) = Config.getTab(tab);
let (tabname, screen, screenOptionsConfig) =
Config.getTab(tab, makeNavigationProp());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makeNavigationProp in the future will accept original navigation prop. How do we handle that case? I know that the status of navigation prop is in WIP but I'm wondering how we handle this

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder that too 😉 We need to discuss that. You, me and @grabbou

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should handle that just like we handle it in StackNavigator ->

let makeNavigationProp = (navigation: NavigationProp.t) => {
push: route =>
NavigationProp.push(
navigation,
containerDisplayName,
routeProps(~route),
),
pop: _route => (),
};

Copy link
Contributor

@grabbou grabbou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @vnovick for working on it! I left few comments, in particular related to the navigation property to unblock you.

Looking forward to reviewing the final version!

let tabBarOptions: tabBarOptions;
let getTab:
tabs => (Js.Dict.key, navigation => ReasonReact.reactElement, screenOptions);
(tabs, navigation) =>
(Js.Dict.key, unit => ReasonReact.reactElement, screenOptions);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does "screen" has to be a function?

unit => ReasonReact.reactElement

I would unify it with StackNavigator and just make it a React element. It will make the API much easier. If we need a functional form, we can always wrap it later on our side.

let tabBarOptions: tabBarOptions;
let getTab:
tabs => (Js.Dict.key, navigation => ReasonReact.reactElement, screenOptions);
(tabs, navigation) =>
(Js.Dict.key, unit => ReasonReact.reactElement, screenOptions);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need users to define a string of a route explicitly. I know that TabNavigator's router requires us to use a concept of string to register a route.

We can do better.

There are two ways of handling that:

a) StackNavigator's way - we define only one "route", let's call it Container. Every "route" is a "" element that accepts current screen to render as a prop. For example, "" where "EditUser(5)" could be a ReasonML variant.

b) Define a hashing function that can generate a UUID based on a variant it is given. For example, for "EditUser(5)", this could be "Route_EditUser_5". It's representation is not important as long as the function is stable and can generate same string for a given variant. This will be only used internally by the React Navigation.

Given that TabNavigator doesn't have StackNavigator's limitations, I propose we go with "b" for the sake of simplicity. We can always change it later, transparently for the end users.

[@bs.send] external goBack: unit => unit = "goBack";
};

let makeNavigationProp = () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should accept a "navigation" prop so that we can actually talk to a real "navigation". See how StackNavigation handles that. The code will be exactly the same, except for the "routeName" part. Depending on the approach you take, this will be either similar to StackNavigation (passing variant to a Container route) or generating a hash (to be used as a routeName) from a given variant.

Either way, "navigate" should accept a "tab" (variant) instead of a "routeName" (string). "NavigationProp.navigate" is good - ReactNavigation operates on "string"s and we should keep it that way.

let tabs =
Config.order
|> List.map(tab => {
let (tabname, screen, screenOptionsConfig) = Config.getTab(tab);
let (tabname, screen, screenOptionsConfig) =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As already said, "tabName" could be generated dynamically. "screen" doesn't have to be a function, we can wrap it here if needed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants