From 33e22729ee7317f5afecb79f06b4f873dc3e376d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Dombya?= <135591453+hervedombya@users.noreply.github.com> Date: Thu, 28 Nov 2024 11:22:41 +0100 Subject: [PATCH] Update react-router to v6 and refactor navigation hooks in components --- package-lock.json | 118 +++++------------- package.json | 4 +- .../emptystate/Emptystate.component.tsx | 6 +- .../tablev2/SearchWithQueryParams.tsx | 6 +- .../components/tabsv2/Tabsv2.component.tsx | 102 +++++++-------- .../AttachmentConfirmationModal.tsx | 14 +-- 6 files changed, 93 insertions(+), 157 deletions(-) diff --git a/package-lock.json b/package-lock.json index baf0fc5e4e..54197fd4fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,8 +27,8 @@ "react-dropzone": "^14.2.3", "react-hook-form": "^7.49.2", "react-query": "^3.34.0", - "react-router": "5.2.0", - "react-router-dom": "5.2.0", + "react-router": "^6.28.0", + "react-router-dom": "^6.28.0", "react-select": "4.3.1", "react-table": "^7.7.0", "react-test-renderer": "^18.3.1", @@ -3576,6 +3576,14 @@ "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", "dev": true }, + "node_modules/@remix-run/router": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz", + "integrity": "sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -12458,19 +12466,6 @@ "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" }, - "node_modules/history": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", - "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", - "dependencies": { - "@babel/runtime": "^7.1.2", - "loose-envify": "^1.2.0", - "resolve-pathname": "^3.0.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0", - "value-equal": "^1.0.1" - } - }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -13790,7 +13785,8 @@ "node_modules/isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "dev": true }, "node_modules/isbinaryfile": { "version": "4.0.10", @@ -16795,20 +16791,6 @@ "node": ">=4" } }, - "node_modules/mini-create-react-context": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz", - "integrity": "sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dependencies": { - "@babel/runtime": "^7.12.1", - "tiny-warning": "^1.0.3" - }, - "peerDependencies": { - "prop-types": "^15.0.0", - "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -18884,55 +18866,35 @@ } }, "node_modules/react-router": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.2.0.tgz", - "integrity": "sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw==", - "dependencies": { - "@babel/runtime": "^7.1.2", - "history": "^4.9.0", - "hoist-non-react-statics": "^3.1.0", - "loose-envify": "^1.3.1", - "mini-create-react-context": "^0.4.0", - "path-to-regexp": "^1.7.0", - "prop-types": "^15.6.2", - "react-is": "^16.6.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz", + "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==", + "dependencies": { + "@remix-run/router": "1.21.0" + }, + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "react": ">=15" + "react": ">=16.8" } }, "node_modules/react-router-dom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.2.0.tgz", - "integrity": "sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA==", + "version": "6.28.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.0.tgz", + "integrity": "sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==", "dependencies": { - "@babel/runtime": "^7.1.2", - "history": "^4.9.0", - "loose-envify": "^1.3.1", - "prop-types": "^15.6.2", - "react-router": "5.2.0", - "tiny-invariant": "^1.0.2", - "tiny-warning": "^1.0.0" + "@remix-run/router": "1.21.0", + "react-router": "6.28.0" + }, + "engines": { + "node": ">=14.0.0" }, "peerDependencies": { - "react": ">=15" - } - }, - "node_modules/react-router/node_modules/path-to-regexp": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", - "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", - "dependencies": { - "isarray": "0.0.1" + "react": ">=16.8", + "react-dom": ">=16.8" } }, - "node_modules/react-router/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" - }, "node_modules/react-select": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/react-select/-/react-select-4.3.1.tgz", @@ -19625,11 +19587,6 @@ "node": ">=4" } }, - "node_modules/resolve-pathname": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", - "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==" - }, "node_modules/resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -21579,12 +21536,8 @@ "node_modules/tiny-invariant": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", - "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==" - }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true }, "node_modules/title-case": { "version": "2.1.1", @@ -22581,11 +22534,6 @@ "spdx-expression-parse": "^3.0.0" } }, - "node_modules/value-equal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", - "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==" - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", diff --git a/package.json b/package.json index bb7dce11c3..a868848960 100644 --- a/package.json +++ b/package.json @@ -115,8 +115,8 @@ "react-dropzone": "^14.2.3", "react-hook-form": "^7.49.2", "react-query": "^3.34.0", - "react-router": "5.2.0", - "react-router-dom": "5.2.0", + "react-router": "^6.28.0", + "react-router-dom": "^6.28.0", "react-select": "4.3.1", "react-table": "^7.7.0", "react-test-renderer": "^18.3.1", diff --git a/src/lib/components/emptystate/Emptystate.component.tsx b/src/lib/components/emptystate/Emptystate.component.tsx index 41c95b8e7a..a39e412593 100644 --- a/src/lib/components/emptystate/Emptystate.component.tsx +++ b/src/lib/components/emptystate/Emptystate.component.tsx @@ -4,7 +4,7 @@ import { Button } from '../buttonv2/Buttonv2.component'; import { Icon, IconName } from '../icon/Icon.component'; import { LargeText } from '../text/Text.component'; import { CoreUITheme } from '../../style/theme'; -import { useHistory } from 'react-router'; +import { useNavigate } from 'react-router'; export type Props = { listedResource: { @@ -48,7 +48,7 @@ export const ActionWrapper = styled.div` function EmptyState(props: Props) { const { icon, listedResource, link, resourceToCreate, backgroundColor } = props; - const history = useHistory(); + const navigate = useNavigate(); return ( } type="button" variant="primary" - onClick={() => history.push(link)} + onClick={() => navigate(link)} /> )} diff --git a/src/lib/components/tablev2/SearchWithQueryParams.tsx b/src/lib/components/tablev2/SearchWithQueryParams.tsx index 12890c4ab7..8efbda41f5 100644 --- a/src/lib/components/tablev2/SearchWithQueryParams.tsx +++ b/src/lib/components/tablev2/SearchWithQueryParams.tsx @@ -1,5 +1,5 @@ import { useState } from 'react'; -import { useLocation, useHistory } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import { TableSearch as Search, SearchProps } from './Search'; export type SearchWithQueryParamsProps = { @@ -10,7 +10,7 @@ export type SearchWithQueryParamsProps = { export function SearchWithQueryParams(props: SearchWithQueryParamsProps) { const { queryParams = 'search', onChange, ...rest } = props; const { search, pathname } = useLocation(); - const history = useHistory(); + const navigate = useNavigate(); const params = new URLSearchParams(search); const initialValue = params.get(queryParams) || ''; const [value, setValue] = useState(initialValue); @@ -18,7 +18,7 @@ export function SearchWithQueryParams(props: SearchWithQueryParamsProps) { function handleOnChange(value: string) { const { onChange } = props; params.set(queryParams, value); - history.replace(`${pathname}?${params.toString()}`); + navigate(`${pathname}?${params.toString()}`, { replace: true }); setValue(value); if (typeof onChange === 'function') { diff --git a/src/lib/components/tabsv2/Tabsv2.component.tsx b/src/lib/components/tabsv2/Tabsv2.component.tsx index f7ff371c3a..c81176648a 100644 --- a/src/lib/components/tabsv2/Tabsv2.component.tsx +++ b/src/lib/components/tabsv2/Tabsv2.component.tsx @@ -1,33 +1,25 @@ import React, { createContext, + ReactElement, + useCallback, useEffect, useState, - useCallback, - ReactElement, } from 'react'; +import { Route, Routes, useLocation, useNavigate } from 'react-router-dom'; +import styled from 'styled-components'; +import { ButtonIcon } from '../buttonv2/Buttonv2.component'; +import { BasicText, EmphaseText, SecondaryText } from '../text/Text.component'; +import { ScrollButton } from './ScrollButton'; import { - TabBar, ScrollableContainer, + TabBar, TabContent, TabItem, TabsContainer, TabsScroller, } from './StyledTabs'; -import { - useHistory, - useLocation, - useRouteMatch, - matchPath, - Route, - Switch, -} from 'react-router-dom'; -import { SecondaryText, BasicText, EmphaseText } from '../text/Text.component'; -import { ScrollButton } from './ScrollButton'; -import { Tab } from './Tab'; -import { TabProps, Query } from './Tab'; +import { Query, Tab, TabProps } from './Tab'; import { useScrollingTabs } from './useScrollingTabs'; -import { ButtonIcon } from '../buttonv2/Buttonv2.component'; -import styled from 'styled-components'; type TabsProps = { activeTabColor?: string; @@ -59,8 +51,8 @@ function Tabs({ ...rest }: TabsProps) { const location = useLocation(); - const history = useHistory(); - const { url } = useRouteMatch(); + const navigate = useNavigate(); + const url = location.pathname; const [selectedTabIndex, setSelectedTabIndex] = useState< number | null | undefined >(null); @@ -110,15 +102,13 @@ function Tabs({ useEffect(() => { let hasSelectedTab = false; filteredTabsChildren.forEach((child, index) => { + const fullPath = child.props.path.startsWith('/') + ? child.props.path + : url + '/' + child.props.path; + const isSelected = - !!matchPath(location.pathname, { - path: child.props.path.startsWith('/') - ? child.props.path - : url + '/' + child.props.path, - exact: child.props.exact, - strict: child.props.strict, - sensitive: child.props.sensitive, - }) && (child.props.query ? matchQuery(child.props.query) : true); + location.pathname.match(new RegExp(`^${fullPath}$`, 'i')) && + (child.props.query ? matchQuery(child.props.query) : true); if (isSelected) { setSelectedTabIndex(index); @@ -127,6 +117,7 @@ function Tabs({ }); if (!hasSelectedTab) setSelectedTabIndex(null); }, [location.pathname, filteredTabsChildren, matchQuery]); + const { scrollButtonEndRef, scrollButtonStartRef, @@ -154,7 +145,7 @@ function Tabs({ className={`sc-tabs-item ${isSelected ? 'selected' : ''}`} key={index} role="tab" - onClick={() => history.push(getPushHistoryPath(path, query))} + onClick={() => navigate(getPushHistoryPath(path, query))} selected={isSelected} tabHoverColor={tabHoverColor} inactiveTabColor={inactiveTabColor} @@ -168,7 +159,7 @@ function Tabs({ event.key === 'Spacebar' ) { event.preventDefault(); - history.push(getPushHistoryPath(path, query)); + navigate(getPushHistoryPath(path, query)); } }} {...childRest} @@ -218,33 +209,30 @@ function Tabs({ /> )} - - {filteredTabsChildren.map((tab, index) => ( - - {!tab.props.query || - (tab.props.query && matchQuery(tab.props.query)) ? ( - - {tab.props.children} - - ) : ( - <> - )} - - ))} + + {filteredTabsChildren.map((tab, index) => ( + + {tab.props.children} + + ) : null + } + /> + ))} + ); @@ -252,4 +240,4 @@ function Tabs({ Tabs.Tab = Tab; // re-export Tab -export { Tabs, Tab }; +export { Tab, Tabs }; diff --git a/src/lib/organisms/attachments/AttachmentConfirmationModal.tsx b/src/lib/organisms/attachments/AttachmentConfirmationModal.tsx index 2a9bbce229..54f2cc4aed 100644 --- a/src/lib/organisms/attachments/AttachmentConfirmationModal.tsx +++ b/src/lib/organisms/attachments/AttachmentConfirmationModal.tsx @@ -1,11 +1,11 @@ import { ComponentType, useState } from 'react'; -import { Column, Table } from '../../components/tablev2/Tablev2.component'; -import { Box, Button } from '../../next'; import { useMutation, UseMutationOptions } from 'react-query'; -import { AttachmentOperation, AttachmentAction } from './AttachmentTypes'; +import { useNavigate } from 'react-router'; import { useTheme } from 'styled-components'; -import { useHistory } from 'react-router'; import { Icon, LargerText, Modal, SecondaryText, Stack, Wrap } from '../..'; +import { Column, Table } from '../../components/tablev2/Tablev2.component'; +import { Box, Button } from '../../next'; +import { AttachmentAction, AttachmentOperation } from './AttachmentTypes'; type AttachmentStatus = 'Waiting for confirmation' | 'Error' | 'Success'; @@ -50,7 +50,7 @@ export function AttachmentConfirmationModal< failedOperations: AttachmentOperation[], ) => void; }) { - const history = useHistory(); + const navigate = useNavigate(); const [isModalOpen, setIsModalOpen] = useState(false); @@ -135,7 +135,7 @@ export function AttachmentConfirmationModal< onExit(successfulOperations, failedOperations); } handleClose(); - history.push(redirectUrl); + navigate(redirectUrl); }; const modalFooter = () => { return ( @@ -284,7 +284,7 @@ export function AttachmentConfirmationModal< disabled={cancelButtonDisabled} onClick={() => { if (onCancel) onCancel(); - history.push(redirectUrl); + navigate(redirectUrl); }} />