I have a Browser Context set up like this:
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<BrowserRouter>
<ErrorBoundary FallbackComponent={CustomError}>
<App />
</ErrorBoundary>
</BrowserRouter>
</React.StrictMode>,
)
and the app component is like this:
export const App = () => {
if (isDevEnv()) {
const navigate = useNavigate();
const restoreOriginalUri = async (originalUri: string) => {
navigate(toRelativeUrl(originalUri || '/', window.location.origin));
};
return (
<Security restoreOriginalUri={restoreOriginalUri}>
<AppRoutes />
</Security>
)
}
return (
<AppRoutes />
)
}
At this point everything works just fine, but eslint complains that react hook cannot be used conditionally.
I decided to make the code beautifully, so that eslint would not complain. For that I separated DEV logic into a subcomponent like this:
App.tsx become very short. All logic moved to a subcomponent:
export const App = () => {
const children: React.JSX.Element = <AppRoutes />;
return <MySecurityComponent children={children} />
}
the MySecurityComponent
is like this:
type MySecurityComponentType = (props: { children: React.JSX.Element }) => React.JSX.Element;
export const MySecurityComponent: MySecurityComponentType = ({children}): React.JSX.Element => {
if (isDevEnv()) {
return <MySecurityComponentDev children={children} />
}
}
return children;
}
And a MySecurityComponentDev
(sub-sub component) looks like this:
type MySecurityComponentDevType = (props: { children: React.JSX.Element }) => React.JSX.Element;
const MySecurityComponentDev: MySecurityComponentDevType = ({ children }) => {
const navigate = useNavigate();
const restoreOriginalUri = async originalUri: string) => {
navigate(toRelativeUrl(originalUri || '/', window.location.origin));
};
return (
<Security restoreOriginalUri={restoreOriginalUri}>
{children}
</Security>
);
}
And now I see such an error:
useNavigate() may be used only in the context of a <Router> component.
Am I missing something to push the router context through the tree of components?
Or it is allowed to use router context only in a top-level children and inside routes?
2
Answers
I managed to solve the issue with react router context. The router context is accessible in the root component (App), but it is not accessible in the child components, which are not inside the Routes/Route. I tried to get the "useNavigation" in the App component and pass it through the children with props. And it worked out! And ESLint does not complain!!!
I think you’ve overcomplicated your code a bit. The most trivial solution is simply to call the
useNavigate
hook from the first code example from the correct place, e.g. the React component body. It will be in scope.