Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: react-router v6.4 Data APIs integration #423

Open
izzm opened this issue Jul 22, 2024 · 10 comments
Open

[Feature]: react-router v6.4 Data APIs integration #423

izzm opened this issue Jul 22, 2024 · 10 comments
Assignees
Labels
enhancement New feature or request

Comments

@izzm
Copy link

izzm commented Jul 22, 2024

Is your feature request related to a problem? Please describe.

react-router v6.4 provides new API to routers and new routes definitions. And documentation recommends to use new API https://reactrouter.com/en/main/routers/picking-a-router for a new projects.

Describe the solution you'd like

Ability to use telegram-apps BrowserNavigator along with new react-router API.

Describe alternatives you've considered

Manually show/hide back button using router, initialized by createBrowserRouter method and tracking location using useLocation hook;

const location = useLocation();
const backButton = useBackButton();
const navigate = useNavigate();

useEffect(() => {
  if (location.pathname === "/" && backButton.isVisible) {
    backButton.hide();
  } else if (location.pathname !== "/" && !backButton.isVisible) {
    backButton.show();
  }
}, [location, backButton]);

useEffect(() => {
  backButton.on("click", () => navigate(-1), true);
}, [backButton, navigate]);

Additional context

No response

@izzm izzm added the enhancement New feature or request label Jul 22, 2024
@heyqbnk
Copy link
Member

heyqbnk commented Jul 23, 2024

What is the difference with the current implementation?

https://docs.telegram-mini-apps.com/packages/telegram-apps-react-router-integration

@izzm
Copy link
Author

izzm commented Jul 23, 2024

In 6.4 react-router introduces new Data API with async data loaders and actions, component lazy loading and other stuff https://reactrouter.com/en/main/routers/picking-a-router#data-apis.

This new methods available only while initializing a router in a new way - using function call, for example createBrowserRouter and using RouterProvider component to attach router to the React component tree.

@heyqbnk
Copy link
Member

heyqbnk commented Jul 23, 2024

But createBrowserRouter creates a BrowserRouter. We don't need it, don't we? We need a router based on a custom navigator. That's why we implemented react-router-integration

@izzm
Copy link
Author

izzm commented Jul 23, 2024

Yes, we need a custom router. With react-router-integration routes are defined in pre-6.4 style, for example (snippet from documentation):

return (
  <Router location={location} navigator={reactNavigator}>
    <Routes>
      <Route path={'/'} component={IndexPage}/>
      <Route path={'*'} element={<Navigate href={'/'}/>}/>
    </Routes>
  </Router>
);

location and reactNavigator are objects, created by react-router-integration, and it works perfectly. React router version 6.4+ provides new way to attach routes to React component tree, new versions uses RouterProvider component, which allow new features of react router to be used.

New api officially not expose base createRouter method, but it can be imported directly from '@remix-run/router' package (which is not recommended by https://github.com/remix-run/react-router/tree/main/packages/router, but this is the only way I found to implement a custom router). This method get history argument with a type History, which is similar to Navigator, but have few additional properties. location is moved to history property.

For the integration with a new react-router API react-router-integration needs to return an object, compatible with a History type.

@izzm
Copy link
Author

izzm commented Jul 23, 2024

I create a workaround for 6.4+ style routes definition:

import {
  Action,
  createRouter,
  Path,
  To,
  type History,
} from "@remix-run/router";

...


const navigator = useMemo(() => initNavigator("app-navigation-state"), []);
const [location, reactNavigator] = useIntegration(navigator);

useEffect(() => {
  navigator.attach();
  return () => navigator.detach();
}, [navigator]);

const history: History = {
  location,
  push: reactNavigator.push,
  replace: reactNavigator.replace,
  action: Action.Pop,
  createHref: reactNavigator.createHref,
  createURL: (to: To) => {
    return new URL(reactNavigator.createHref(to), window.location.toString());
  },
  encodeLocation: (to: To) => {
    return (
      reactNavigator.encodeLocation?.(to) ||
      ({ pathname: "/", search: "", hash: "" } as Path)
    );
  },
  go: reactNavigator.go,
  listen: () => {
    return () => {};
  },
};

const routes = ... // define you routes here
const router = createRouter({ routes, history }).initialize();

return (<RouterProvider router={router} />);

Maybe, it will be better to implement this in react-router-integration?

@GrayYoung
Copy link

listen: () => {
return () => {};
},

It works, but the Back button does not respond.

@oviedo97fer
Copy link

I create a workaround for 6.4+ style routes definition:

import {
  Action,
  createRouter,
  Path,
  To,
  type History,
} from "@remix-run/router";

...


const navigator = useMemo(() => initNavigator("app-navigation-state"), []);
const [location, reactNavigator] = useIntegration(navigator);

useEffect(() => {
  navigator.attach();
  return () => navigator.detach();
}, [navigator]);

const history: History = {
  location,
  push: reactNavigator.push,
  replace: reactNavigator.replace,
  action: Action.Pop,
  createHref: reactNavigator.createHref,
  createURL: (to: To) => {
    return new URL(reactNavigator.createHref(to), window.location.toString());
  },
  encodeLocation: (to: To) => {
    return (
      reactNavigator.encodeLocation?.(to) ||
      ({ pathname: "/", search: "", hash: "" } as Path)
    );
  },
  go: reactNavigator.go,
  listen: () => {
    return () => {};
  },
};

const routes = ... // define you routes here
const router = createRouter({ routes, history }).initialize();

return (<RouterProvider router={router} />);

Maybe, it will be better to implement this in react-router-integration?

Any update about this?
I use this approach and back button (or navigate(-1)) only changes url but react app doesnt react about that change

@izzm
Copy link
Author

izzm commented Oct 2, 2024

Any update about this?
I use this approach and back button (or navigate(-1)) only changes url but react app doesnt react about that change

Try to use navigator.back(); to call navigator, returned by initNavigator. I didn't test this behavior, because I decide to use standard ReactRouter's createBrowserRouter with back button workaload, described in a first message, instead of custom router.

@heyqbnk
Copy link
Member

heyqbnk commented Oct 2, 2024

Hey guys. I decided to postpone the development of the navigation package (and React router integration as well), so it is better to use the standard React routing utilities for now.

We will go back to this topic after some time

@oviedo97fer
Copy link

Any update about this?
I use this approach and back button (or navigate(-1)) only changes url but react app doesnt react about that change

Try to use navigator.back(); to call navigator, returned by initNavigator. I didn't test this behavior, because I decide to use standard ReactRouter's createBrowserRouter with back button workaload, described in a first message, instead of custom router.

Thank you! I finally made the same decision

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants