I m getting typescript error when I tried to upgraded React-router-dom v5 to v6, How can I fix this typescript error. below you can find the code Thanks in advance
`
export function withRouter(ui: React.ReactElement) {
const history = useNavigate();
const routerValues: any = {
history: undefined,
location: undefined
};
const result = (
<MemoryRouter>
{ui}
<Route
path="*"
element={({ history, location }) => {
routerValues.history = history;
routerValues.location = location;
return null;
}}
/>
</MemoryRouter>
below you can find entire file code `
import React from "react";
import { Reducer } from "@reduxjs/toolkit";
import { Provider } from "react-redux";
import { MemoryRouter, Route, useNavigate } from "react-router-dom";
import buildStore from "../redux/store";
export function withRedux(
ui: React.ReactElement,
reducer: {
[key: string]: Reducer;
},
initialState: any
) {
const store = buildStore(initialState, true);
const dispatchSpy = jest.spyOn(store, "dispatch");
return {
result: <Provider store={store}>{ui}</Provider>,
store,
dispatchSpy
};
}
export function withRouter(ui: React.ReactElement) {
const history = useNavigate();
const routerValues: any = {
history: undefined,
location: undefined
};
const result = (
<MemoryRouter>
{ui}
<Route
path="*"
element={({ history, location }) => {
routerValues.history = history;
routerValues.location = location;
return null;
}}
/>
</MemoryRouter>
);
return { result, routerValues };
}
`
I am passing history and location props which were work fine when I was using react router v5 here is the previous code : `
const result = (
<MemoryRouter>
{ui}
<Route
path="*"
render={({ history, location }) => {
routerValues.history = history;
routerValues.location = location;
return null;
}}
/>
</MemoryRouter>
`
After update react router v6 I changed in my code because We know that v6 no longer support render keyword inside route So I Replace it
`
const result = (
<MemoryRouter>
{ui}
<Route
path="*"
element={({ history, location }) => {
routerValues.history = history;
routerValues.location = location;
return null;
}}
/>
</MemoryRouter>
);
`
But I don't have Idea in v6 How can I pass these props inside route
CodePudding user response:
Try this:
export function withRouter(ui: React.ReactElement) {
const history = useNavigate();
const location = useLocation();
const routerValues: any = {
history: history,
location: location
};
const result = (
<MemoryRouter>
{ui}
</MemoryRouter>
);
return { result, routerValues };
}
CodePudding user response:
Issues
- The
withRouter
Higher Order Component/render function can't use the RRD hooks outside the router it is rendering. react-router-dom@6
Route
components don't take "route props" and theelement
prop takes aReact.ReactNode
, a.k.a. JSX. The "route props" should be passed as props to the component being rendered.
Solution
You'll need to create two components. One is a test render function that provides the MemoryRouter
as a test wrapper, and the other is a correct withRouter
HOC.
Example: Create a custom render function that renders the component under test into a wrapper component that provides all the various contexts (routers, redux, etc)
import { render } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
const Wrappers = ({ children }) => (
<MemoryRouter>
{children}
</MemoryRouter>
);
const customRender = (ui: React.ReactElement, options: object) => {
return render(ui, { wrapper: Wrappers, ...options });
};
export { customRender as render };
See the RTL setup docs for more information on custom render functions.
Create separate withRouter
HOC to only decorate older React Class components that can't use the RRD hooks directly. Here's an example Typescript implementation.
import { ComponentType } from 'react';
import {
Location,
NavigateFunction,
useLocation,
useParams
} from 'react-router-dom';
export interface WithRouterProps {
location: Location;
navigate: NavigateFunction;
params: ReturnType<typeof useParams>;
}
export const withRouter = <P extends object>(Component: ComponentType<P>) =>
(props: Omit<P, keyof WithRouterProps>) => {
const location = useLocation();
const params = useParams();
const navigate = useNavigate();
return (
<Component
{...props}
{...{ location, params, navigate }}
/>
);
};