简体   繁体   中英

Getting error when I try to upgrade react-router v5 to V6

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>

enter image description here `

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

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 };
}

Issues

  1. The withRouter Higher Order Component/render function can't use the RRD hooks outside the router it is rendering.
  2. react-router-dom@6 Route components don't take "route props" and the element prop takes a React.ReactNode , aka 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 }}
      />
    );
  };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM