diff --git a/apps/platform/.env b/apps/platform/.env
index 66185f29a..fd275121a 100644
--- a/apps/platform/.env
+++ b/apps/platform/.env
@@ -1,3 +1,3 @@
-VITE_API_URL=https://api.partner-platform.dev.opentargets.xyz/api/v4/graphql
+VITE_API_URL=https://api.platform.dev.opentargets.xyz/api/v4/graphql
VITE_AI_API_URL=https://dev-ai-api-w37vlfsidq-ew.a.run.app
VITE_PROFILE=default
diff --git a/apps/platform/package.json b/apps/platform/package.json
index 794bea94c..f12f0c5bd 100644
--- a/apps/platform/package.json
+++ b/apps/platform/package.json
@@ -34,7 +34,7 @@
"react-dropzone": "^14.2.3",
"react-gtm-module": "^2.0.11",
"react-helmet": "^6.0.0",
- "react-router-dom": "5.1.2",
+ "react-router-dom": "6.28.0",
"react-tsparticles": "^2.0.6",
"sections": "*",
"smiles-drawer": "^1.1.22",
diff --git a/apps/platform/src/App.tsx b/apps/platform/src/App.tsx
index a211cf2be..50279f113 100644
--- a/apps/platform/src/App.tsx
+++ b/apps/platform/src/App.tsx
@@ -1,4 +1,4 @@
-import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
+import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import { ApolloProvider } from "@apollo/client";
import { ThemeProvider, SearchProvider, PrivateRoute, ConfigurationProvider } from "ui";
@@ -33,49 +33,28 @@ function App(): ReactElement {
searchPlaceholder="Search for a target, drug, disease, or phenotype..."
>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
+ }
+ />
+ {/* } /> */}
+
diff --git a/apps/platform/src/components/AssociationsToolkit/components/Table/CellName.jsx b/apps/platform/src/components/AssociationsToolkit/components/Table/CellName.jsx
index 4b93fe916..14c361fd3 100644
--- a/apps/platform/src/components/AssociationsToolkit/components/Table/CellName.jsx
+++ b/apps/platform/src/components/AssociationsToolkit/components/Table/CellName.jsx
@@ -21,7 +21,7 @@ import {
faBezierCurve,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
-import { useHistory } from "react-router-dom";
+import { useNavigate } from "react-router-dom";
import useAotfContext from "../../hooks/useAotfContext";
import { ENTITIES, isPartnerPreview, TABLE_PREFIX } from "../../utils";
import { grey } from "@mui/material/colors";
@@ -85,7 +85,7 @@ const ContextMenuContainer = styled("div", {
}));
function CellName({ cell, colorScale }) {
- const history = useHistory();
+ const navigate = useNavigate();
const contextMenuRef = useRef();
const { entityToGet, pinnedEntries, setPinnedEntries, id: currentEntityId } = useAotfContext();
const { loading, prefix } = cell.table.getState();
@@ -180,15 +180,15 @@ function CellName({ cell, colorScale }) {
};
const handleNavigateToProfile = () => {
- history.push(profileURL);
+ navigate(profileURL);
};
const handleNavigateToAssociations = () => {
- history.push(associationsURL);
+ navigate(associationsURL);
};
const handleNavigateToEvidence = () => {
- history.push(evidenceURL);
+ navigate(evidenceURL);
};
const loadingWidth = entityToGet === ENTITIES.TARGET ? 50 : 150;
diff --git a/apps/platform/src/pages/CredibleSetPage/CredibleSetPage.tsx b/apps/platform/src/pages/CredibleSetPage/CredibleSetPage.tsx
index 5202289f3..55b2b3b6e 100644
--- a/apps/platform/src/pages/CredibleSetPage/CredibleSetPage.tsx
+++ b/apps/platform/src/pages/CredibleSetPage/CredibleSetPage.tsx
@@ -1,5 +1,5 @@
import { useQuery } from "@apollo/client";
-import { useLocation, useParams, Switch, Route, useRouteMatch, Link } from "react-router-dom";
+import { useLocation, useParams, Routes, Route, useMatch, Link } from "react-router-dom";
import { Box, Tabs, Tab } from "@mui/material";
import { BasePage, ScrollToTop } from "ui";
import Header from "./Header";
@@ -10,7 +10,7 @@ import Profile from "./Profile";
function CredibleSetPage() {
const location = useLocation();
const { studyLocusId } = useParams() as { studyLocusId: string };
- const { path } = useRouteMatch();
+ const { path } = useMatch();
const { loading, data } = useQuery(CREDIBLE_SET_PAGE_QUERY, {
variables: { studyLocusId: studyLocusId },
@@ -62,7 +62,7 @@ function CredibleSetPage() {
)}
/>
-
+
-
+
);
}
diff --git a/apps/platform/src/pages/DiseasePage/DiseasePage.tsx b/apps/platform/src/pages/DiseasePage/DiseasePage.tsx
index cff0d0ba2..c2a3f07a9 100644
--- a/apps/platform/src/pages/DiseasePage/DiseasePage.tsx
+++ b/apps/platform/src/pages/DiseasePage/DiseasePage.tsx
@@ -1,7 +1,7 @@
import { ReactElement } from "react";
import { useQuery } from "@apollo/client";
import { Box, Tab, Tabs } from "@mui/material";
-import { Link, Redirect, Route, Switch, useLocation, useParams } from "react-router-dom";
+import { Link, Navigate, Route, Routes, useLocation, useParams } from "react-router-dom";
import { BasePage, ScrollToTop } from "ui";
import Header from "./Header";
@@ -44,7 +44,7 @@ function DiseasePage(): ReactElement {
>
- (
@@ -64,18 +64,14 @@ function DiseasePage(): ReactElement {
)}
- />
-
-
-
-
-
-
-
-
-
-
-
+ /> */}
+
+ } />
+ } />
+ {/*
+
+ */}
+
);
}
diff --git a/apps/platform/src/pages/DrugPage/DrugPage.jsx b/apps/platform/src/pages/DrugPage/DrugPage.jsx
index 92f384dbc..0c448d9ac 100644
--- a/apps/platform/src/pages/DrugPage/DrugPage.jsx
+++ b/apps/platform/src/pages/DrugPage/DrugPage.jsx
@@ -1,15 +1,7 @@
import { useQuery } from "@apollo/client";
import { BasePage, ScrollToTop } from "ui";
import { Box, Tabs, Tab } from "@mui/material";
-import {
- useLocation,
- useParams,
- Switch,
- Route,
- useRouteMatch,
- Link,
- Redirect,
-} from "react-router-dom";
+import { useLocation, useParams, Routes, Route, useMatch, Link, Navigate } from "react-router-dom";
import Header from "./Header";
import NotFoundPage from "../NotFoundPage";
@@ -20,7 +12,7 @@ import Profile from "./Profile";
function DrugPage() {
const location = useLocation();
const { chemblId } = useParams();
- const { path } = useRouteMatch();
+ const { path } = useMatch();
const { loading, data } = useQuery(DRUG_PAGE_QUERY, {
variables: { chemblId },
@@ -56,14 +48,14 @@ function DrugPage() {
)}
/>
-
+
-
+
-
+
);
}
diff --git a/apps/platform/src/pages/SearchPage/SearchPage.jsx b/apps/platform/src/pages/SearchPage/SearchPage.jsx
index f17c12888..d89142190 100644
--- a/apps/platform/src/pages/SearchPage/SearchPage.jsx
+++ b/apps/platform/src/pages/SearchPage/SearchPage.jsx
@@ -1,7 +1,7 @@
import { useState, useEffect, lazy, Suspense } from "react";
import queryString from "query-string";
import { Typography } from "@mui/material";
-import { useLocation, useHistory } from "react-router-dom";
+import { useLocation, useNavigate } from "react-router-dom";
import { LoadingBackdrop, EmptyPage, BasePage } from "ui";
import client from "../../client";
@@ -28,7 +28,7 @@ const parseQueryString = qs => {
function SearchPage() {
const location = useLocation();
- const history = useHistory();
+ const navigate = useNavigate();
const { q, page, entities } = parseQueryString(location.search);
const [data, setData] = useState(null);
@@ -57,7 +57,7 @@ function SearchPage() {
const handleChangePage = (event, pageChanged) => {
const params = { q, page: pageChanged + 1, entities };
const qs = queryString.stringify(params, QS_OPTIONS);
- history.push(`/search?${qs}`);
+ navigate(`/search?${qs}`);
};
const handleSetEntity = entity => (event, checked) => {
@@ -67,7 +67,7 @@ function SearchPage() {
entities: checked ? [...entities, entity] : entities.filter(e => e !== entity),
};
const qs = queryString.stringify(params, QS_OPTIONS);
- history.push(`/search?${qs}`);
+ navigate(`/search?${qs}`);
};
let SEARCH_CONTAINER = null;
diff --git a/apps/platform/src/pages/StudyPage/StudyPage.tsx b/apps/platform/src/pages/StudyPage/StudyPage.tsx
index 81dba7ef6..f75073977 100644
--- a/apps/platform/src/pages/StudyPage/StudyPage.tsx
+++ b/apps/platform/src/pages/StudyPage/StudyPage.tsx
@@ -1,15 +1,7 @@
import { useQuery } from "@apollo/client";
import { BasePage, ScrollToTop } from "ui";
import { Box, Tabs, Tab } from "@mui/material";
-import {
- useLocation,
- useParams,
- Switch,
- Route,
- useRouteMatch,
- Link,
- Redirect,
-} from "react-router-dom";
+import { useLocation, useParams, Routes, Route, useMatch, Link, Navigate } from "react-router-dom";
import Header from "./Header";
import NotFoundPage from "../NotFoundPage";
import STUDY_PAGE_QUERY from "./StudyPage.gql";
@@ -18,7 +10,7 @@ import Profile from "./Profile";
function StudyPage() {
const location = useLocation();
const { studyId } = useParams() as { studyId: string };
- const { path } = useRouteMatch();
+ const { path } = useMatch();
const { loading, data } = useQuery(STUDY_PAGE_QUERY, {
variables: { studyId },
@@ -63,7 +55,7 @@ function StudyPage() {
)}
/>
-
+
-
+
-
+
);
}
diff --git a/apps/platform/src/pages/TargetPage/TargetPage.tsx b/apps/platform/src/pages/TargetPage/TargetPage.tsx
index d59368d6d..8f36aa8be 100644
--- a/apps/platform/src/pages/TargetPage/TargetPage.tsx
+++ b/apps/platform/src/pages/TargetPage/TargetPage.tsx
@@ -1,15 +1,7 @@
import { ReactElement } from "react";
import { useQuery } from "@apollo/client";
import { Box, Tab, Tabs } from "@mui/material";
-import {
- Link,
- Route,
- Switch,
- useLocation,
- useRouteMatch,
- useParams,
- Redirect,
-} from "react-router-dom";
+import { Link, Route, Routes, useLocation, useMatch, useParams, Navigate } from "react-router-dom";
import { BasePage, ScrollToTop } from "ui";
import Header from "./Header";
@@ -27,7 +19,7 @@ type TargetURLParams = {
function TargetPage(): ReactElement {
const location = useLocation();
const { ensgId } = useParams();
- const { path } = useRouteMatch();
+ const { path } = useMatch();
const { loading, data } = useQuery(TARGET_PAGE_QUERY, {
variables: { ensgId },
@@ -90,7 +82,7 @@ function TargetPage(): ReactElement {
)}
/>
-
+
@@ -98,9 +90,9 @@ function TargetPage(): ReactElement {
-
+
-
+
);
}
diff --git a/apps/platform/src/pages/VariantPage/VariantPage.tsx b/apps/platform/src/pages/VariantPage/VariantPage.tsx
index 02ae6d28b..0846ab6d2 100644
--- a/apps/platform/src/pages/VariantPage/VariantPage.tsx
+++ b/apps/platform/src/pages/VariantPage/VariantPage.tsx
@@ -1,5 +1,5 @@
import { useQuery } from "@apollo/client";
-import { useLocation, useParams, Switch, Route, useRouteMatch, Link } from "react-router-dom";
+import { useLocation, useParams, Routes, Route, useMatch, Link } from "react-router-dom";
import { Box, Tabs, Tab } from "@mui/material";
import { BasePage, ScrollToTop } from "ui";
import Header from "./Header";
@@ -10,7 +10,7 @@ import Profile from "./Profile";
function VariantPage() {
const location = useLocation();
const { varId } = useParams() as { varId: string };
- const { path } = useRouteMatch();
+ const { path } = useMatch();
const { loading, data } = useQuery(VARIANT_PAGE_QUERY, {
variables: { variantId: varId },
@@ -44,11 +44,11 @@ function VariantPage() {
)}
/>
-
+
-
+
);
}
diff --git a/packages/sections/package.json b/packages/sections/package.json
index 6371354a4..ad537efca 100644
--- a/packages/sections/package.json
+++ b/packages/sections/package.json
@@ -35,7 +35,7 @@
"react": "^18.2.0",
"react-helmet": "^6.0.0",
"react-measure": "^2.1.2",
- "react-router-dom": "5.1.2",
+ "react-router-dom": "6.28.0",
"recoil": "^0.3.0",
"smiles-drawer": "^1.1.22",
"tsparticles": "^2.0.6",
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 6aa53223a..4f808f704 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -30,7 +30,7 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-helmet": "^6.1.0",
- "react-router-dom": "5.1.2",
+ "react-router-dom": "6.28.0",
"react-scroll": "^1.8.9",
"uuid": "^9.0.1"
},
diff --git a/packages/ui/src/components/EntityPanel/EntityPanel.tsx b/packages/ui/src/components/EntityPanel/EntityPanel.tsx
new file mode 100644
index 000000000..ff1abb7e5
--- /dev/null
+++ b/packages/ui/src/components/EntityPanel/EntityPanel.tsx
@@ -0,0 +1,4 @@
+function EntityPanel() {
+ return
EntityPanel
;
+}
+export default EntityPanel;
diff --git a/packages/ui/src/components/PrivateRoute.jsx b/packages/ui/src/components/PrivateRoute.jsx
index b97146241..bae2973ae 100644
--- a/packages/ui/src/components/PrivateRoute.jsx
+++ b/packages/ui/src/components/PrivateRoute.jsx
@@ -1,11 +1,11 @@
-import { Redirect } from "react-router-dom";
+import { Navigate } from "react-router-dom";
import usePermissions from "../hooks/usePermissions";
function PrivateRoute({ children }) {
const { isPartnerPreview } = usePermissions();
if (!isPartnerPreview) {
- return ;
+ return ;
}
return children;
diff --git a/packages/ui/src/components/RoutingTabs/RoutingTabs.jsx b/packages/ui/src/components/RoutingTabs/RoutingTabs.jsx
index 78a8de315..a00179f92 100644
--- a/packages/ui/src/components/RoutingTabs/RoutingTabs.jsx
+++ b/packages/ui/src/components/RoutingTabs/RoutingTabs.jsx
@@ -1,12 +1,12 @@
import { Suspense, Children, cloneElement } from "react";
-import { generatePath, Route, Switch, useHistory, useRouteMatch } from "react-router-dom";
+import { generatePath, Route, Routes, useNavigate, useMatch } from "react-router-dom";
import { Tabs, Box } from "@mui/material";
import { v1 } from "uuid";
import LoadingBackdrop from "../LoadingBackdrop";
function RoutingTabs({ children }) {
- const match = useRouteMatch();
- const history = useHistory();
+ const match = useMatch();
+ const history = useNavigate();
const routes = [];
const preparedChildren = Children.map(children, child => {
@@ -31,7 +31,7 @@ function RoutingTabs({ children }) {
{preparedChildren}
}>
-
+
{routes.map((route, index) => (
))}
-
+
>
);
diff --git a/packages/ui/src/components/ScrollToTop.tsx b/packages/ui/src/components/ScrollToTop.tsx
index 41bf06c62..c0940afab 100644
--- a/packages/ui/src/components/ScrollToTop.tsx
+++ b/packages/ui/src/components/ScrollToTop.tsx
@@ -1,20 +1,14 @@
-import { Component } from "react";
-import { RouteComponentProps, withRouter } from "react-router-dom";
+import { useEffect } from "react";
+import { useLocation } from "react-router-dom";
-class ScrollToTop extends Component {
- componentDidMount() {
- window.scrollTo(0, 0);
- }
+const ScrollToTop = () => {
+ const location = useLocation();
- componentDidUpdate(prevProps: RouteComponentProps) {
- if (this.props.location.pathname !== prevProps.location.pathname) {
- window.scrollTo(0, 0);
- }
- }
+ useEffect(() => {
+ window.scrollTo(0, 0);
+ }, [location.pathname]);
- render() {
- return null;
- }
-}
+ return null;
+};
-export default withRouter(ScrollToTop);
+export default ScrollToTop;
diff --git a/packages/ui/src/hooks/useListOption.js b/packages/ui/src/hooks/useListOption.js
index 2199d8415..4f7621adc 100644
--- a/packages/ui/src/hooks/useListOption.js
+++ b/packages/ui/src/hooks/useListOption.js
@@ -1,8 +1,8 @@
-import { useHistory } from "react-router-dom";
+import { useNavigate } from "react-router-dom";
import { addSearchToLocalStorage } from "../components/GlobalSearch/utils/searchUtils";
function useListOption() {
- const history = useHistory();
+ const navigate = useNavigate();
const openListItem = option => {
if (!option) return;
@@ -11,16 +11,14 @@ function useListOption() {
addSearchToLocalStorage(newOption);
if (newOption.entity === "search") {
- history.push(`/search?q=${newOption.name}&page=1`);
+ navigate(`/search?q=${newOption.name}&page=1`);
} else if (newOption.entity === "study") {
- history.push(`/${newOption.entity}/${newOption.studyId}`);
+ navigate(`/${newOption.entity}/${newOption.studyId}`);
} else {
- history.push(
+ navigate(
`/${newOption.entity}/${newOption.id}${
- newOption.entity !== "drug" && newOption.entity !== "variant"
- ? "/associations"
- : ""
- }`
+ newOption.entity !== "drug" && newOption.entity !== "variant" ? "/associations" : ""
+ }`
);
}
};
diff --git a/packages/ui/src/hooks/useStateParams.ts b/packages/ui/src/hooks/useStateParams.ts
index c90a5a692..961127042 100644
--- a/packages/ui/src/hooks/useStateParams.ts
+++ b/packages/ui/src/hooks/useStateParams.ts
@@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
-import { useHistory } from "react-router-dom";
+import { useLocation, useNavigate } from "react-router-dom";
function useStateParams(
initialState: T,
@@ -7,8 +7,9 @@ function useStateParams(
serialize: (state: T) => string,
deserialize: (state: string) => T
): [T, (state: T) => void] {
- const history = useHistory();
- const search = new URLSearchParams(history.location.search);
+ const navigate = useNavigate();
+ const location = useLocation();
+ const search = new URLSearchParams(location.search);
const existingValue = search.get(paramsName);
const [state, setState] = useState(existingValue ? deserialize(existingValue) : initialState);
@@ -22,10 +23,10 @@ function useStateParams(
const onChange = (s: T) => {
setState(s);
- const searchParams = new URLSearchParams(history.location.search);
+ const searchParams = new URLSearchParams(location.search);
searchParams.set(paramsName, serialize(s));
- const { pathname } = history.location;
- history.push({ pathname, search: searchParams.toString() });
+ const { pathname } = location;
+ navigate({ pathname, search: searchParams.toString() });
};
return [state, onChange];
diff --git a/packages/ui/src/index.tsx b/packages/ui/src/index.tsx
index 818efb463..813621526 100644
--- a/packages/ui/src/index.tsx
+++ b/packages/ui/src/index.tsx
@@ -39,6 +39,7 @@ export { default as ApiPlaygroundDrawer } from "./components/ApiPlaygroundDrawer
export { default as OtTable } from "./components/OtTable/OtTable";
export { default as OtPopper } from "./components/OtPopper";
export { default as OtScoreLinearBar } from "./components/OtScoreLinearBar";
+export { default as EntityPanel } from "./components/EntityPanel/EntityPanel";
export { default as EmptyPage } from "./pages/EmptyPage";
export { default as NotFoundPage } from "./pages/NotFoundPage";
diff --git a/yarn.lock b/yarn.lock
index cde279ecb..509d20496 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2778,6 +2778,11 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
+"@remix-run/router@1.21.0":
+ version "1.21.0"
+ resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.21.0.tgz#c65ae4262bdcfe415dbd4f64ec87676e4a56e2b5"
+ integrity sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==
+
"@repeaterjs/repeater@3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca"
@@ -6494,7 +6499,7 @@ d3-array@2, d3-array@^2.3.0, d3-array@^2.8.0:
dependencies:
internmap "^1.0.0"
-"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0, d3-array@^3.2.4:
+"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0:
version "3.2.4"
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5"
integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==
@@ -14421,6 +14426,14 @@ react-router-dom@5.1.2:
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
+react-router-dom@6.28.0:
+ version "6.28.0"
+ resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.28.0.tgz#f73ebb3490e59ac9f299377062ad1d10a9f579e6"
+ integrity sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==
+ dependencies:
+ "@remix-run/router" "1.21.0"
+ react-router "6.28.0"
+
react-router@5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.1.2.tgz#6ea51d789cb36a6be1ba5f7c0d48dd9e817d3418"
@@ -14437,6 +14450,13 @@ react-router@5.1.2:
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
+react-router@6.28.0:
+ version "6.28.0"
+ resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.28.0.tgz#29247c86d7ba901d7e5a13aa79a96723c3e59d0d"
+ integrity sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==
+ dependencies:
+ "@remix-run/router" "1.21.0"
+
react-scripts@4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-4.0.3.tgz#b1cafed7c3fa603e7628ba0f187787964cb5d345"