Repository: kyeotic/raviger (ts)

Issue:
Problems with navigation and nested routes
Hi, I've found some strange problems with navigation when you are using nested routes with params. I'm testing with the latest version 1.4.

## How to reproduce?
Here is the link to the reproduction code:
https://stackblitz.com/edit/react-raviger-test?file=index.js

Press on the links in the bottom part in that order to:
1. nested with a param About (the route is loaded)
2. nested with a param Test (the route is **not** loaded)
3. root (the route is loaded)
4. nested with a param Test (the route is loaded)
5. root (the route is loaded)
6. nested with a param Test (the route is loaded)
7. nested with a param About (the route is **not** loaded)

![raviger-bug](https://user-images.githubusercontent.com/227305/80435097-f6cf9b80-893e-11ea-94fc-3f89056979fd.gif)


## Possible cause
I've checked many things, and I think the `useLocationChange` hook is the main suspect. It looks like [the if condition with `inheritBasePath` option](https://github.com/kyeotic/raviger/blob/1e7992cf08fafd6ac7429197a2b08bdbd450d9ad/src/path.js#L51) is causing the problem. I haven't found any other place where this option is used internally.

I was trying to debug the code with breakpoints in browser devtools. After setting the value of `basePath` to what is provided with `options` the issue is gone:
<img width="633" alt="inheritBasePath-hack" src="https://user-images.githubusercontent.com/227305/80434568-7197b700-893d-11ea-8297-e32bb0493214.png">
![raviger-fixed](https://user-images.githubusercontent.com/227305/80434884-5d07ee80-893e-11ea-8509-2c3a243c6027.gif)

Do you reckon we could somehow fix this behaviour? Maybe we just need to remove the `inheritBasePath` condition 😄 or force the `false` value when using hook internally from the `useRoutes` hook?

Pull request:
Nested use path
This should fix #50 

I tried to verify this, but I don't have time to fully vet it tonight but I want to unblock @macku so I am publishing under the `beta` tag

```
npm i raviger@beta
OR
npm i raviger@1.4.1-0
```

I will vet tomorrow and release on proper if it looks good.

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fe47f32..72aaff8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [1.4.1] - 2020-04-28
+### Fixed
+- `usePath` sets `inheritBasePath: false` when using provided `basePath`
+
 ## [1.4.0] - 2020-03-18
 ### Added
 - `<Redirect>` Component
diff --git a/example/src/NestedApp.js b/example/src/NestedApp.js
new file mode 100644
index 0000000..3932a66
--- /dev/null
+++ b/example/src/NestedApp.js
@@ -0,0 +1,78 @@
+import React, { Component } from 'react'
+import { render } from 'react-dom'
+import {
+  useRoutes,
+  usePath,
+  useBasePath,
+  useQueryParams,
+  navigate,
+  Link
+} from '../../src/main.js'
+
+const NotFound = () => {
+  return (
+    <div style={{ border: '1px solid red' }} data-testid="label">
+      not found
+    </div>
+  )
+}
+
+function Harness({ routes, basePath }) {
+  const route = useRoutes(routes, { basePath }) || <NotFound />
+
+  const contextPath = usePath()
+  const contextBasePath = useBasePath()
+
+  return (
+    <>
+      <div style={{ border: '1px solid blue' }}>
+        <h1>Router wrapper</h1>
+        <p>Path: {contextPath}</p>
+        <p>BasePath: {contextBasePath}</p>
+      </div>
+      {route}
+    </>
+  )
+}
+
+function Route({ label, extra }) {
+  let path = usePath()
+  let basePath = useBasePath()
+  return (
+    <div style={{ border: '1px solid green' }}>
+      <h1>Route</h1>
+      <p data-testid="label">Label: "{label}"</p>
+      <p>Path: "{path}"</p>
+      <p>Base Path: "{basePath}"</p>
+      <p>Param: "{extra}"</p>
+    </div>
+  )
+}
+
+const nestedRoutes = {
+  '/': () => <Route label="nested root" />,
+  '/about': () => <Route label="nested about" />,
+  '/test': () => <Route label="nested test" />
+}
+
+const routes = {
+  '/': () => <Route label="root" />,
+  '/test/*': () => <Harness basePath={`/foo/test`} routes={nestedRoutes} />,
+  '/:param*': ({ param }) => (
+    <Harness basePath={`/foo/${param}`} routes={nestedRoutes} />
+  )
+}
+
+export default function App() {
+  return (
+    <div>
+      <Harness routes={routes} basePath="/foo" />
+
+      <Link href="/foo/">root</Link>
+      <br />
+      <Link href="/foo/1234/about">nested with a param About</Link>
+      <br />
+      <Link href="/foo/1234/test">nested with a param Test</Link>
+    </div>
+  )
+}
diff --git a/example/src/index.js b/example/src/index.js
index 91bb031..3824a08 100644
--- a/example/src/index.js
+++ b/example/src/index.js
@@ -1,6 +1,7 @@
 import React from 'react'
 import ReactDOM from 'react-dom'
-import App from './App'
+// import App from './App'
+import App from './NestedApp.js'
 // eslint-disable-next-line import/no-unresolved
 import whyDidYouRender from 'whyDidYouRender'
 
diff --git a/package-lock.json b/package-lock.json
index a6204d4..55cb1f4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "raviger",
-  "version": "1.4.0",
+  "version": "1.4.1-0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/package.json b/package.json
index 360b88b..c6b3d39 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "raviger",
-  "version": "1.4.0",
+  "version": "1.4.1-0",
   "description": "React routing with hooks",
   "main": "dist/main.js",
   "module": "dist/module.js",
diff --git a/src/path.js b/src/path.js
index fb2b1ab..c01f006 100644
--- a/src/path.js
+++ b/src/path.js
@@ -7,7 +7,7 @@ export function usePath(basePath) {
   let contextBasePath = useBasePath() // hooks can't be called conditionally
   basePath = basePath || contextBasePath
   let [path, setPath] = useState(getCurrentPath(basePath))
-  useLocationChange(setPath, { basePath })
+  useLocationChange(setPath, { basePath, inheritBasePath: !basePath })
   return path
 }
 


Test patch:
diff --git a/test/path.spec.js b/test/path.spec.js
index 9504378..3d41c64 100644
--- a/test/path.spec.js
+++ b/test/path.spec.js
@@ -87,6 +87,38 @@ describe('usePath', () => {
     expect(getByTestId('path')).toHaveTextContent('/about')
     expect(getByTestId('path')).not.toHaveTextContent('/nested')
   })
+
+  test('has correct path for nested base path', async () => {
+    function Harness({ routes, basePath }) {
+      const route = useRoutes(routes, { basePath })
+      return route
+    }
+
+    const nestedRoutes = {
+      '/': () => <Route />,
+      '/about': () => <Route />,
+      '/info': () => <Route />
+    }
+    const routes = {
+      '/': () => <Route />,
+      '/about': () => <Route />,
+      '/nested*': () => <Harness basePath="/foo/nested" routes={nestedRoutes} />
+    }
+
+    const { getByTestId } = render(<Harness routes={routes} basePath="/foo" />)
+    act(() => navigate('/foo'))
+    expect(getByTestId('path')).toHaveTextContent('/')
+
+    act(() => navigate('/foo/nested/about'))
+    expect(getByTestId('path')).toHaveTextContent('/about')
+
+    // Yes, check twice
+    // This is a regression check for this bug: https://github.com/kyeotic/raviger/issues/50
+    act(() => navigate('/foo/nested/info'))
+    expect(getByTestId('path')).toHaveTextContent('/')
+    act(() => navigate('/foo/nested/info'))
+    expect(getByTestId('path')).toHaveTextContent('/')
+  })
 })
 
 describe('useHash', () => {