Skip to content

Commit

Permalink
more fixes in Upgrade_20230121_ReactRouter6
Browse files Browse the repository at this point in the history
  • Loading branch information
olmobrutall committed Jan 30, 2023
1 parent 094fab5 commit 76755e7
Showing 1 changed file with 3 additions and 3 deletions.
6 changes: 3 additions & 3 deletions Signum.Upgrade/Upgrades/Upgrade_20230121_ReactRouter6.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ public override void Execute(UpgradeContext uctx)
file.ReplaceBetweenIncluded(a => a.Contains("function reload() {"),
a => a.Contains(".then(() => {"), """
async function reload() {
await AuthClient.autoLogin()
await reloadTypes()
await CultureClient.loadCurrentCulture()
await AuthClient.autoLogin();
await reloadTypes();
await CultureClient.loadCurrentCulture();
""");

file.ReplaceBetweenIncluded(a => a.Contains("const promise"),
Expand Down

1 comment on commit 76755e7

@olmobrutall
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Upgrade to react-router 6.7.0

One of the dependencies that has been lagging behind for 5 months is react-router because this lirary has a tendency to make big breaking changes and 6 was not an exception.

Changes in react-router 6

This version deprecates most of the API using props (RouteComponentProps) in favour for a new hooks API.

Also the new API encourages a global routes configuration and relative links and routes configuration that helps with Server Side Rendering.

Here some links of the changes in react-router 6:
https://reactrouter.com/en/main/upgrading/v5
https://blog.saeloun.com/2021/12/02/new-features-in-react-router-6.html
https://www.youtube.com/watch?v=Ul3y1LXxzdU

Changes in react-router 6.4

Also in version 6.4 another wave of important changes came, encouraging the use of javascript objects and createBrowserRouter() instead of React Elements and <BrowserRouter>.

This new version also introduces the concept of loaders, to parallelize the loading of data with the loading of javascript modules, but only when using the new internal router instead of the old history dependeny.

https://reactrouter.com/en/main/start/overview
https://www.youtube.com/watch?v=6xqh2f-sV6E

In general, I don't think that most of the changes are very important for the typical LOB Application, but fundational stones for https://remix.run/, framework for building front-facing websites like a catalog.

Problems with ~/ and other braking changes.

Traditionally ASP.Net applications are often deployed in IIS using sub directories urls like http://localhost/MyApp/. In order to make the application portable to othe sub directory, or no sub directory at all, the ~ is used. https://learn.microsoft.com/en-us/previous-versions/aspnet/ms178116(v=vs.100)

This tradition is not common in other web frameworks, where applications in development are typically deployed in another port, like http://localhost:8081.

In order to make app-relative urls unambiguous and simplify IIS deployment, I monkey-pached some react-router classes to support ~/ syntax. Here is how the hack worked.

Unfortunatly, react-router 6 is based on hooks and functional componets, so is not easy to monkey patch.

This means that ~/ is gone... and doesn't work in <Link/>, in navigate ( previously push/ replace), and for consistency also in ajaxGet and ajaxPost. Instead just use / to refer to the beginning of the application.

is ~ really gone? ...ok, not quite. It's there for backward compatibility, but should not be used anymore.

Old Behaviour in toAbsolutUrl and <Link/> (monkey-pached)

export function toAbsoluteUrl(appRelativeUrl: string): string {
  if (appRelativeUrl?.startsWith("~/"))
    return window.__baseUrl + appRelativeUrl.after("~/");

  var relativeCrappyUrl = history.location.pathname.beforeLast("/") + "/~/"; //In Link render ~/ is considered a relative url
  if (appRelativeUrl?.startsWith(relativeCrappyUrl))
    return window.__baseUrl + appRelativeUrl.after(relativeCrappyUrl);

  if (appRelativeUrl?.startsWith(window.__baseUrl) || appRelativeUrl?.startsWith("http"))
    return appRelativeUrl;

  return appRelativeUrl;
}

//Examples
//`~/myPage` -> `/MyApp.React/myPage`  (old Recomended)
//`/MyApp.React/myPage` -> `/MyApp.React/myPage` (For playing safe)
//`/myPage` -> `/myPage`

New Behaviour in toAbsolutUrl, and AppContext.navigate

export function toAbsoluteUrl(appRelativeUrl: string): string {
  if (appRelativeUrl?.startsWith("/") && window.__baseName != "")
    if (!appRelativeUrl.startsWith(window.__baseName))
      return window.__baseName + appRelativeUrl;

  if (appRelativeUrl?.startsWith("~/"))
    return window.__baseName + appRelativeUrl.after("~"); //For backwards compatibility

  return appRelativeUrl;
}

//Examples
//`~/myPage` -> `/MyApp.React/myPage`  (For backwards compatibility with links in the DB, like toolbar)
//`/MyApp.React/myPage` -> `/MyApp.React/myPage` (For playing safe)
//`/myPage` -> `/MyApp.React/myPage` (NEW RECOMMENDED)

New Behaviour in <Link/> or useNavigate

Unfortunatly monkey-paching react-router is no longer possible, so there are some differences in behaviour, but as long as you use app relative urls starting with / everithing will be ok.

//Examples
//`~/myPage` -> `/MyApp.React/myPage`  (NOT SUPPORTED!)
//`/MyApp.React/myPage` -> `/MyApp.React/MyApp.React/myPage` (DUPLICATED APP NAME)
//`/myPage` -> `/MyApp.React/myPage` (NEW RECOMMENDED)

URL Strategy

The rule of thumb is, only use URLS like /myPage and at the very end, when the url is going to be used outside of react-router use toAbsoluteUrl. Examples:

  • window.open(AppContext.toAbsoluteUrl("/myPage")}
  • <a href={AppContext.toAbsoluteUrl("/myPage")}/>
  • <img src={AppContext.toAbsoluteUrl("/myLogo.png")}/>

But don't call toAbsoluteUrl for react-router stuff:

  • <Link to="/myLogo.png" />
  • `navigate("/myLogo.png")

How to Upgrade

Fortunatly Upgrade_20230121_ReactRouter6 should fix 99% of the braking changes. It's a complex upgrade script but should work if your code is idiomatic Signum React code.

This is an example of the changes in Southwind: signumsoftware/southwind@be65dc9

image

Please sign in to comment.