Skip to content

Commit 68371aa

Browse files
authored
useNavigate: Get pathname from useLocation instead of RouteContext (#7982)
1 parent 7c6ff7d commit 68371aa

File tree

2 files changed

+110
-1
lines changed

2 files changed

+110
-1
lines changed

packages/react-router/__tests__/navigate-test.tsx

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as ReactDOM from "react-dom";
33
import { act } from "react-dom/test-utils";
44
import {
55
MemoryRouter as Router,
6+
Outlet,
67
Routes,
78
Route,
89
useNavigate,
@@ -163,4 +164,111 @@ describe("navigate", () => {
163164
expect(node.innerHTML).toMatchInlineSnapshot(`"<h1>About mj</h1>"`);
164165
});
165166
});
167+
168+
describe("with a search param and no pathname", () => {
169+
function Bakery() {
170+
let navigate = useNavigate();
171+
172+
let user = new URLSearchParams(useLocation().search).get("user");
173+
function handleClick() {
174+
navigate({
175+
search: user ? "" : new URLSearchParams({ user: "mj" }).toString()
176+
});
177+
}
178+
179+
return (
180+
<div>
181+
<h1>Bakery</h1>
182+
{user && <p>Welcome {user}</p>}
183+
<Outlet />
184+
<button onClick={handleClick}>{user ? "logout" : "login"}</button>
185+
</div>
186+
);
187+
}
188+
189+
function Muffins() {
190+
return <h2>Yay, muffins!</h2>;
191+
}
192+
193+
function About() {
194+
let user = new URLSearchParams(useLocation().search).get("user");
195+
return <h1>About {user}</h1>;
196+
}
197+
198+
it("resolves using the current location", () => {
199+
act(() => {
200+
ReactDOM.render(
201+
<Router initialEntries={["/bakery/muffins"]}>
202+
<Routes>
203+
<Route path="bakery" element={<Bakery />}>
204+
<Route path="muffins" element={<Muffins />} />
205+
</Route>
206+
<Route path="about" element={<About />} />
207+
</Routes>
208+
</Router>,
209+
node
210+
);
211+
});
212+
213+
let button = node.querySelector("button");
214+
215+
act(() => {
216+
button?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
217+
});
218+
219+
expect(node.innerHTML).toMatchInlineSnapshot(
220+
`"<div><h1>Bakery</h1><p>Welcome mj</p><h2>Yay, muffins!</h2><button>logout</button></div>"`
221+
);
222+
});
223+
});
224+
225+
describe("with a hash param and no pathname", () => {
226+
function Bakery() {
227+
let navigate = useNavigate();
228+
function handleClick() {
229+
navigate({
230+
hash: "#about"
231+
});
232+
}
233+
234+
return (
235+
<div>
236+
<h1>Bakery</h1>
237+
<button onClick={handleClick}>About us</button>
238+
<Outlet />
239+
<h2 id="about">About us</h2>
240+
<p>We bake delicious cakes!</p>
241+
</div>
242+
);
243+
}
244+
245+
function Muffins() {
246+
return <h2>Yay, muffins!</h2>;
247+
}
248+
249+
it("resolves using the current location", () => {
250+
act(() => {
251+
ReactDOM.render(
252+
<Router initialEntries={["/bakery/muffins"]}>
253+
<Routes>
254+
<Route path="bakery" element={<Bakery />}>
255+
<Route path="muffins" element={<Muffins />} />
256+
</Route>
257+
</Routes>
258+
</Router>,
259+
node
260+
);
261+
});
262+
263+
let button = node.querySelector("button");
264+
265+
act(() => {
266+
button?.dispatchEvent(new MouseEvent("click", { bubbles: true }));
267+
});
268+
269+
expect(node.innerHTML).toMatchInlineSnapshot(
270+
`"<div><h1>Bakery</h1><button>About us</button><h2>Yay, muffins!</h2><h2 id=\\"about\\">About us</h2><p>We bake delicious cakes!</p></div>"`
271+
);
272+
});
273+
});
166274
});

packages/react-router/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,8 @@ export function useNavigate(): NavigateFunction {
413413
);
414414

415415
let navigator = React.useContext(NavigatorContext);
416-
let { pathname, basename } = React.useContext(RouteContext);
416+
let { basename } = React.useContext(RouteContext);
417+
let { pathname } = useLocation();
417418

418419
let activeRef = React.useRef(false);
419420
React.useEffect(() => {

0 commit comments

Comments
 (0)