Skip to content

Commit 2e479fe

Browse files
authored
Replace withRouter HOC with useHistory hook (#8721)
Small PR to refactor some technical debt in our React stack. I replaced the `withRouter` HOC from `react-router` with a `useHistory` hook instead. The remaining 6 files with `withRouter` still use React class components. ### Issues: - None ------ (Please delete unneeded items, merge only when none are left open) - [x] Added changelog entry (create a `$PR_NUMBER.md` file in `unreleased_changes` or use `./tools/create-changelog-entry.py`) - [ ] Added migration guide entry if applicable (edit the same file as for the changelog) - [ ] Updated [documentation](../blob/master/docs) if applicable - [ ] Adapted [wk-libs python client](https://github.com/scalableminds/webknossos-libs/tree/master/webknossos/webknossos/client) if relevant API parts change - [ ] Removed dev-only changes like prints and application.conf edits - [ ] Considered [common edge cases](../blob/master/.github/common_edge_cases.md) - [ ] Needs datastore update after deployment
1 parent 7c58f29 commit 2e479fe

File tree

12 files changed

+43
-56
lines changed

12 files changed

+43
-56
lines changed

frontend/javascripts/admin/auth/change_password_view.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,17 @@ import { Alert, Button, Col, Form, Input, Row } from "antd";
33
import Request from "libs/request";
44
import Toast from "libs/toast";
55
import messages from "messages";
6-
import { type RouteComponentProps, withRouter } from "react-router-dom";
6+
import { useHistory } from "react-router-dom";
77
import { logoutUserAction } from "viewer/model/actions/user_actions";
88
import Store from "viewer/store";
99
const FormItem = Form.Item;
1010
const { Password } = Input;
1111

12-
type Props = {
13-
history: RouteComponentProps["history"];
14-
};
15-
1612
const MIN_PASSWORD_LENGTH = 8;
1713

18-
function ChangePasswordView({ history }: Props) {
14+
function ChangePasswordView() {
1915
const [form] = Form.useForm();
16+
const history = useHistory();
2017

2118
function onFinish(formValues: Record<string, any>) {
2219
Request.sendJSONReceiveJSON("/api/auth/changePassword", {
@@ -158,4 +155,4 @@ function ChangePasswordView({ history }: Props) {
158155
);
159156
}
160157

161-
export default withRouter<RouteComponentProps, any>(ChangePasswordView);
158+
export default ChangePasswordView;

frontend/javascripts/admin/auth/finish_reset_password_view.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,16 @@ import { Button, Card, Col, Form, Input, Row } from "antd";
33
import Request from "libs/request";
44
import Toast from "libs/toast";
55
import messages from "messages";
6-
import { type RouteComponentProps, withRouter } from "react-router-dom";
6+
import { useHistory } from "react-router-dom";
77
const FormItem = Form.Item;
88
const { Password } = Input;
99
type Props = {
10-
history: RouteComponentProps["history"];
1110
resetToken: string;
1211
};
1312

1413
function FinishResetPasswordView(props: Props) {
1514
const [form] = Form.useForm();
15+
const history = useHistory();
1616

1717
function onFinish(formValues: Record<string, any>) {
1818
const data = formValues;
@@ -27,7 +27,7 @@ function FinishResetPasswordView(props: Props) {
2727
data,
2828
}).then(() => {
2929
Toast.success(messages["auth.reset_pw_confirmation"]);
30-
props.history.push("/auth/login");
30+
history.push("/auth/login");
3131
});
3232
}
3333

@@ -128,4 +128,4 @@ function FinishResetPasswordView(props: Props) {
128128
);
129129
}
130130

131-
export default withRouter<RouteComponentProps & Props, any>(FinishResetPasswordView);
131+
export default FinishResetPasswordView;

frontend/javascripts/admin/auth/login_view.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import { Card, Col, Row } from "antd";
22
import * as Utils from "libs/utils";
33
import window from "libs/window";
4-
import type { RouteComponentProps } from "react-router-dom";
5-
import { withRouter } from "react-router-dom";
4+
import { useHistory } from "react-router-dom";
65
import LoginForm from "./login_form";
76

87
type Props = {
9-
history: RouteComponentProps["history"];
108
redirect?: string;
119
};
1210

13-
function LoginView({ history, redirect }: Props) {
11+
function LoginView({ redirect }: Props) {
12+
const history = useHistory();
1413
const onLoggedIn = () => {
1514
if (!Utils.hasUrlParam("redirectPage")) {
1615
if (redirect) {
@@ -38,4 +37,4 @@ function LoginView({ history, redirect }: Props) {
3837
);
3938
}
4039

41-
export default withRouter<RouteComponentProps & Props, any>(LoginView);
40+
export default LoginView;

frontend/javascripts/admin/auth/start_reset_password_view.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@ import { Button, Card, Col, Form, Input, Row } from "antd";
33
import Request from "libs/request";
44
import Toast from "libs/toast";
55
import messages from "messages";
6-
import { Link, type RouteComponentProps, withRouter } from "react-router-dom";
6+
import { Link, useHistory } from "react-router-dom";
77
const FormItem = Form.Item;
8-
type Props = {
9-
history: RouteComponentProps["history"];
10-
};
118

12-
function StartResetPasswordView({ history }: Props) {
9+
function StartResetPasswordView() {
1310
const [form] = Form.useForm();
11+
const history = useHistory();
1412

1513
const onFinish = (formValues: Record<string, any>) => {
1614
Request.sendJSONReceiveJSON("/api/auth/startResetPassword", {
@@ -67,4 +65,4 @@ function StartResetPasswordView({ history }: Props) {
6765
);
6866
}
6967

70-
export default withRouter<RouteComponentProps & Props, any>(StartResetPasswordView);
68+
export default StartResetPasswordView;

frontend/javascripts/admin/dataset/dataset_add_view.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@ import DatasetUploadView from "admin/dataset/dataset_upload_view";
44
import { getDatastores } from "admin/rest_api";
55
import { Button, Layout, Modal, Tabs, type TabsProps } from "antd";
66
import features from "features";
7-
import type { History } from "history";
87
import { useFetch } from "libs/react_helpers";
98
import { useWkSelector } from "libs/react_hooks";
109
import React, { useState } from "react";
1110
import { connect } from "react-redux";
12-
import type { RouteComponentProps } from "react-router-dom";
13-
import { withRouter } from "react-router-dom";
11+
import { useHistory } from "react-router-dom";
1412
import type { APIDataStore } from "types/api_types";
1513
import { getReadableURLPart } from "viewer/model/accessors/dataset_accessor";
1614
import { enforceActiveUser } from "viewer/model/accessors/user_accessor";
@@ -33,7 +31,8 @@ const addTypeToVerb: Record<DatasetAddType, string> = {
3331
compose: "created",
3432
};
3533

36-
function DatasetAddView({ history }: RouteComponentProps) {
34+
function DatasetAddView() {
35+
const history = useHistory();
3736
const datastores = useFetch<APIDataStore[]>(getDatastores, [], []);
3837
const [datasetId, setDatasetId] = useState("");
3938
const [uploadedDatasetName, setUploadedDatasetName] = useState("");
@@ -267,15 +266,15 @@ const mapStateToProps = (state: WebknossosState) => ({
267266
});
268267

269268
const connector = connect(mapStateToProps);
270-
export default connector(withRouter(DatasetAddView));
269+
export default connector(DatasetAddView);
271270

272271
const getPostUploadModal = (
273272
datasetNeedsConversion: boolean,
274273
datasetAddType: DatasetAddType,
275274
datasetId: string,
276275
uploadedDatasetName: string,
277276
setDatasetId: (arg0: string) => void,
278-
history: History<unknown>,
277+
history: ReturnType<typeof useHistory>,
279278
) => {
280279
return (
281280
<Modal

frontend/javascripts/admin/project/project_create_view.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,11 @@ import { enforceActiveUser } from "viewer/model/accessors/user_accessor";
1414
import { FormItemWithInfo } from "../../dashboard/dataset/helper_components";
1515

1616
const FormItem = Form.Item;
17-
type OwnProps = {
17+
type Props = {
1818
projectId?: string | null | undefined;
1919
};
20-
type Props = OwnProps;
21-
type PropsWithRouter = Props;
2220

23-
function ProjectCreateView({ projectId }: PropsWithRouter) {
21+
function ProjectCreateView({ projectId }: Props) {
2422
const [teams, setTeams] = useState<APITeam[]>([]);
2523
const [users, setUsers] = useState<APIUser[]>([]);
2624
const [isFetchingData, setIsFetchingData] = useState<boolean>(false);

frontend/javascripts/admin/scripts/script_create_view.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ import { createScript, getScript, getTeamManagerOrAdminUsers, updateScript } fro
22
import { Button, Card, Form, Input, Select } from "antd";
33
import { useEffect, useState } from "react";
44
import { connect } from "react-redux";
5-
import type { RouteComponentProps } from "react-router-dom";
6-
import { withRouter } from "react-router-dom";
5+
import { useHistory } from "react-router-dom";
76
import type { APIUser } from "types/api_types";
87
import { enforceActiveUser } from "viewer/model/accessors/user_accessor";
98
import type { WebknossosState } from "viewer/store";
@@ -16,11 +15,9 @@ type StateProps = {
1615
activeUser: APIUser;
1716
};
1817
type Props = OwnProps & StateProps;
19-
type PropsWithRouter = Props & {
20-
history: RouteComponentProps["history"];
21-
};
2218

23-
function ScriptCreateView({ scriptId, activeUser, history }: PropsWithRouter) {
19+
function ScriptCreateView({ scriptId, activeUser }: Props) {
20+
const history = useHistory();
2421
const [users, setUsers] = useState<APIUser[]>([]);
2522
const [isFetchingData, setIsFetchingData] = useState<boolean>(false);
2623
const [form] = Form.useForm();
@@ -135,4 +132,4 @@ const mapStateToProps = (state: WebknossosState): StateProps => ({
135132
});
136133

137134
const connector = connect(mapStateToProps);
138-
export default connector(withRouter<RouteComponentProps & Props, any>(ScriptCreateView));
135+
export default connector(ScriptCreateView);

frontend/javascripts/admin/task/task_create_form_view.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,7 @@ import { Vector3Input, Vector6Input } from "libs/vector_input";
4242
import _ from "lodash";
4343
import messages from "messages";
4444
import React, { useEffect, useState } from "react";
45-
import type { RouteComponentProps } from "react-router-dom";
46-
import { withRouter } from "react-router-dom";
45+
import { useHistory } from "react-router-dom";
4746
import type { APIDataset, APIProject, APIScript, APITask, APITaskType } from "types/api_types";
4847
import type { Vector3, Vector6 } from "viewer/constants";
4948
import type { BoundingBoxObject } from "viewer/store";
@@ -291,7 +290,6 @@ export function ReloadResourceButton({
291290

292291
type Props = {
293292
taskId: string | null | undefined;
294-
history: RouteComponentProps["history"];
295293
};
296294

297295
type FormValues = {
@@ -309,7 +307,8 @@ type FormValues = {
309307
neededExperience: NewTask["neededExperience"];
310308
};
311309

312-
function TaskCreateFormView({ taskId, history }: Props) {
310+
function TaskCreateFormView({ taskId }: Props) {
311+
const history = useHistory();
313312
const { modal } = App.useApp();
314313
const [form] = Form.useForm<FormValues>();
315314

@@ -811,4 +810,4 @@ function TaskCreateFormView({ taskId, history }: Props) {
811810
);
812811
}
813812

814-
export default withRouter<RouteComponentProps & Props, any>(TaskCreateFormView);
813+
export default TaskCreateFormView;

frontend/javascripts/admin/tasktype/task_type_create_view.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ import { useFetch } from "libs/react_helpers";
99
import { jsonStringify } from "libs/utils";
1010
import _ from "lodash";
1111
import { useEffect, useState } from "react";
12-
import type { RouteComponentProps } from "react-router-dom";
13-
import { withRouter } from "react-router-dom";
12+
import { useHistory } from "react-router-dom";
1413
import {
1514
type APIAllowedMode,
1615
type APIMagRestrictions,
@@ -27,7 +26,6 @@ const { TextArea } = Input;
2726

2827
type Props = {
2928
taskTypeId?: string | null | undefined;
30-
history: RouteComponentProps["history"];
3129
};
3230

3331
type FormValues = {
@@ -75,7 +73,8 @@ function isMaximumMagnificationSmallerThenMinRule(value: number | undefined, min
7573
);
7674
}
7775

78-
function TaskTypeCreateView({ taskTypeId, history }: Props) {
76+
function TaskTypeCreateView({ taskTypeId }: Props) {
77+
const history = useHistory();
7978
const [useRecommendedConfiguration, setUseRecommendedConfiguration] = useState(false);
8079
const [isFetchingData, setIsFetchingData] = useState(true);
8180
const [form] = Form.useForm<FormValues>();
@@ -502,4 +501,4 @@ function TaskTypeCreateView({ taskTypeId, history }: Props) {
502501
);
503502
}
504503

505-
export default withRouter<RouteComponentProps & Props, any>(TaskTypeCreateView);
504+
export default TaskTypeCreateView;

frontend/javascripts/components/credits_footer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Layout } from "antd";
2-
import { Link, type RouteComponentProps, withRouter } from "react-router-dom";
2+
import { Link } from "react-router-dom";
33
const { Footer } = Layout;
44

55
const creditsFooter = () => (
@@ -68,4 +68,4 @@ const creditsFooter = () => (
6868
</Footer>
6969
);
7070

71-
export default withRouter<RouteComponentProps, any>(creditsFooter);
71+
export default creditsFooter;

frontend/javascripts/components/redirect.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import { useEffectOnlyOnce } from "libs/react_hooks";
22
import type React from "react";
3-
import type { RouteComponentProps } from "react-router-dom";
4-
import { withRouter } from "react-router-dom";
3+
import { useHistory } from "react-router-dom";
54

65
type Props = {
76
redirectTo: () => Promise<string>;
8-
history: RouteComponentProps["history"];
97
pushToHistory?: boolean;
108
};
119

12-
const AsyncRedirect: React.FC<Props> = ({ redirectTo, history, pushToHistory = true }) => {
10+
const AsyncRedirect: React.FC<Props> = ({ redirectTo, pushToHistory = true }) => {
11+
const history = useHistory();
1312
useEffectOnlyOnce(() => {
1413
const redirect = async () => {
1514
const newPath = await redirectTo();
@@ -38,4 +37,4 @@ const AsyncRedirect: React.FC<Props> = ({ redirectTo, history, pushToHistory = t
3837
return null;
3938
};
4039

41-
export default withRouter<RouteComponentProps & Props, any>(AsyncRedirect);
40+
export default AsyncRedirect;

unreleased_changes/8721.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
### Changed
2+
- Replaced withRouter HOC with useHistory hook for several components.

0 commit comments

Comments
 (0)