Some navigations have no link to click: a form that just saved, a session that just expired, a countdown that reaches zero. useNavigate() returns a function that changes the location programmatically.
const navigate = useNavigate();
async function onSubmit(e) {
e.preventDefault();
const { id } = await createProduct(new FormData(e.currentTarget));
navigate(`/products/${id}`, { replace: true, state: { justCreated: true } });
}navigate(to) pushes a new entry. navigate(to, { replace: true }) overwrites the current one — the right call after a save, so Back does not return to a form already submitted. navigate(n) with a number moves through the stack instead: navigate(-1) is Back, navigate(1) is Forward. The options also take state, preventScrollReset and relative, and to may be relative just as <Link to> is.
React Router 5 139,386 handed a single mutable history object to every routed component. Version 8 has no such object; each of its jobs became a hook. push, replace, goBack and goForward are the navigate calls above; history.location is useLocation(), history.action is useNavigationType(), history.block is useBlocker() in data mode only, and history.length is no longer exposed at all.
Two traps. Do not call navigate during render — it is a side effect, and React 7,897 will warn; navigate from an event handler, or render a <Navigate> element (Redirects and No Match). And do not confuse useNavigate with useNavigation: the first starts a navigation, the second describes one already in flight.