Skip to content

Commit b2f3dc2

Browse files
committed
Minor hook simplification
1 parent d4d9548 commit b2f3dc2

File tree

8 files changed

+74
-72
lines changed

8 files changed

+74
-72
lines changed

frontend/src/api/RetroTokenService.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@ export class RetroTokenService {
3636
public async getRetroTokenForUser(
3737
retroId: string,
3838
userToken: string,
39+
signal: AbortSignal,
3940
): Promise<string> {
4041
const response = await fetch(
4142
`${this.apiBase}/auth/tokens/${encodeURIComponent(retroId)}/user`,
4243
{
4344
method: 'GET',
4445
cache: 'no-cache',
4546
headers: { Authorization: `Bearer ${userToken}` },
47+
signal,
4648
},
4749
);
4850
const body = await handleResponse(response);

frontend/src/components/RetroRouter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ function useRetroReducer(
2727
): RetroReducerState {
2828
const [location, setLocation] = useLocation();
2929
const [retroState, setRetroState] = useState<Retro | null>(null);
30-
const [connected, setConnected] = useState<boolean>(false);
30+
const [connected, setConnected] = useState(false);
3131
const [retroDispatch, setRetroDispatch] = useState<RetroDispatch | null>(
3232
null,
3333
);

frontend/src/components/attachments/giphy/GiphyButton.tsx

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { useState, memo } from 'react';
1+
import { memo } from 'react';
22
import { type RetroItemAttachment } from '../../../shared/api-entities';
33
import { useEvent } from '../../../hooks/useEvent';
4+
import { useBoolean } from '../../../hooks/useBoolean';
45
import { Popup } from '../../common/Popup';
56
import { WrappedButton } from '../../common/WrappedButton';
67
import { GiphyPopup } from './GiphyPopup';
@@ -12,11 +13,9 @@ interface PropsT {
1213

1314
export const GiphyButton = memo(
1415
({ defaultAttachment = null, onChange }: PropsT) => {
15-
const [visible, setVisible] = useState(false);
16-
const show = useEvent(() => setVisible(true));
17-
const hide = useEvent(() => setVisible(false));
16+
const visible = useBoolean(false);
1817
const handleSave = useEvent((newAttachment: RetroItemAttachment | null) => {
19-
hide();
18+
visible.setFalse();
2019
onChange(newAttachment);
2120
});
2221

@@ -26,18 +25,18 @@ export const GiphyButton = memo(
2625
key="giphy"
2726
title="Add GIPHY image"
2827
className="open-giphy"
29-
onClick={show}
28+
onClick={visible.setTrue}
3029
/>
3130
<Popup
3231
title="Insert Giphy Image"
33-
keys={{ Escape: hide }}
34-
isOpen={visible}
35-
onClose={hide}
32+
keys={{ Escape: visible.setFalse }}
33+
isOpen={visible.value}
34+
onClose={visible.setFalse}
3635
>
3736
<GiphyPopup
3837
defaultAttachment={defaultAttachment}
3938
onConfirm={handleSave}
40-
onCancel={hide}
39+
onCancel={visible.setFalse}
4140
/>
4241
</Popup>
4342
</>

frontend/src/components/password/PasswordPage.tsx

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { useState, useLayoutEffect, ReactElement } from 'react';
1+
import { useState, ReactElement } from 'react';
2+
import useAwaited from 'react-hook-awaited';
23
import { Header } from '../common/Header';
34
import { Input } from '../common/Input';
45
import { useSubmissionCallback } from '../../hooks/useSubmissionCallback';
@@ -15,7 +16,6 @@ interface PropsT {
1516
export const PasswordPage = ({ slug, retroId }: PropsT): ReactElement => {
1617
const [password, setPassword] = useState('');
1718
const userToken = useUserToken();
18-
const [checkingUser, setCheckingUser] = useState(false);
1919

2020
const [handleSubmit, sending, error] = useSubmissionCallback(async () => {
2121
if (!password) {
@@ -29,31 +29,22 @@ export const PasswordPage = ({ slug, retroId }: PropsT): ReactElement => {
2929
retroTokenTracker.set(retroId, retroToken);
3030
});
3131

32-
useLayoutEffect(() => {
33-
if (!userToken) {
34-
setCheckingUser(false);
35-
return;
36-
}
37-
38-
setCheckingUser(true);
39-
retroTokenService
40-
.getRetroTokenForUser(retroId, userToken)
41-
.then((retroToken) => {
42-
retroTokenTracker.set(retroId, retroToken);
43-
setCheckingUser(false);
44-
})
45-
.catch(() => {
46-
setCheckingUser(false);
47-
});
48-
}, [
49-
userToken,
50-
setCheckingUser,
51-
retroId,
52-
retroTokenService,
53-
retroTokenTracker,
54-
]);
32+
const checkingUser = useAwaited(
33+
async (signal) => {
34+
if (!userToken) {
35+
return;
36+
}
37+
const retroToken = await retroTokenService.getRetroTokenForUser(
38+
retroId,
39+
userToken,
40+
signal,
41+
);
42+
retroTokenTracker.set(retroId, retroToken);
43+
},
44+
[userToken, retroId, retroTokenService, retroTokenTracker],
45+
);
5546

56-
if (checkingUser) {
47+
if (userToken && checkingUser.state === 'pending') {
5748
return (
5849
<article className="page-password-user">
5950
<Header

frontend/src/components/retro-formats/mood/actions/ActionItem.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, memo } from 'react';
1+
import { memo } from 'react';
22
import { classNames } from '../../../../helpers/classNames';
33
import {
44
type RetroItem,
@@ -7,6 +7,7 @@ import {
77
import { ItemEditor } from '../ItemEditor';
88
import { WrappedButton } from '../../../common/WrappedButton';
99
import { useEvent } from '../../../../hooks/useEvent';
10+
import { useBoolean } from '../../../../hooks/useBoolean';
1011
import Tick from '../../../../../resources/tick.svg';
1112
import TickBold from '../../../../../resources/tick-bold.svg';
1213
import './ActionItem.less';
@@ -27,17 +28,15 @@ export const ActionItem = memo(
2728
const handleToggleDone = useEvent(() => onSetDone?.(item.id, !done));
2829
const handleDelete = useEvent(() => onDelete?.(item.id));
2930

30-
const [editing, setEditing] = useState(false);
31-
const handleBeginEdit = useEvent(() => setEditing(true));
32-
const handleCancelEdit = useEvent(() => setEditing(false));
31+
const editing = useBoolean(false);
3332
const handleSaveEdit = useEvent(
3433
(diff: Partial<UserProvidedRetroItemDetails>) => {
35-
setEditing(false);
34+
editing.setFalse();
3635
onEdit!(item.id, diff);
3736
},
3837
);
3938

40-
if (editing) {
39+
if (editing.value) {
4140
return (
4241
<div className="action-item editing">
4342
<ItemEditor
@@ -50,7 +49,7 @@ export const ActionItem = memo(
5049
submitButtonTitle="Save changes"
5150
onSubmit={handleSaveEdit}
5251
onDelete={onDelete ? handleDelete : undefined}
53-
onCancel={handleCancelEdit}
52+
onCancel={editing.setFalse}
5453
autoFocus
5554
/>
5655
</div>
@@ -74,7 +73,7 @@ export const ActionItem = memo(
7473
className="edit"
7574
disabled={!onEdit}
7675
hideIfDisabled
77-
onClick={handleBeginEdit}
76+
onClick={editing.setTrue}
7877
/>
7978
</div>
8079
);

frontend/src/components/retro-formats/mood/categories/MoodItem.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, memo } from 'react';
1+
import { memo } from 'react';
22
import {
33
type RetroItem,
44
type UserProvidedRetroItemDetails,
@@ -7,6 +7,7 @@ import { MoodItemPlain } from './MoodItemPlain';
77
import { MoodItemFocused } from './MoodItemFocused';
88
import { ItemEditor } from '../ItemEditor';
99
import { useEvent } from '../../../../hooks/useEvent';
10+
import { useBoolean } from '../../../../hooks/useBoolean';
1011
import TickBold from '../../../../../resources/tick-bold.svg';
1112
import './MoodItem.less';
1213

@@ -46,17 +47,15 @@ export const MoodItem = memo(
4647
const handleCancel = useEvent(() => onCancel?.(item.id));
4748
const handleContinue = useEvent(() => onContinue?.(item.id));
4849

49-
const [editing, setEditing] = useState(false);
50-
const handleBeginEdit = useEvent(() => setEditing(true));
51-
const handleCancelEdit = useEvent(() => setEditing(false));
50+
const editing = useBoolean(false);
5251
const handleSaveEdit = useEvent(
5352
(diff: Partial<UserProvidedRetroItemDetails>) => {
54-
setEditing(false);
53+
editing.setFalse();
5554
onEdit!(item.id, diff);
5655
},
5756
);
5857

59-
if (editing) {
58+
if (editing.value) {
6059
return (
6160
<div className="mood-item editing">
6261
<ItemEditor
@@ -69,7 +68,7 @@ export const MoodItem = memo(
6968
submitButtonTitle="Save changes"
7069
onSubmit={handleSaveEdit}
7170
onDelete={onDelete ? handleDelete : undefined}
72-
onCancel={handleCancelEdit}
71+
onCancel={editing.setFalse}
7372
allowAttachments
7473
autoFocus
7574
/>
@@ -94,7 +93,7 @@ export const MoodItem = memo(
9493
<MoodItemPlain
9594
item={item}
9695
onVote={onVote ? handleVote : undefined}
97-
onEdit={onEdit ? handleBeginEdit : undefined}
96+
onEdit={onEdit ? editing.setTrue : undefined}
9897
onSelect={onSelect ? handleSelect : undefined}
9998
/>
10099
);

frontend/src/components/retro/RetroPage.tsx

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
import { useState, useRef, memo } from 'react';
1+
import { useRef, memo } from 'react';
22
import { type Retro } from '../../shared/api-entities';
33
import { type RetroPagePropsT } from '../RetroRouter';
44
import { ArchivePopup } from './ArchivePopup';
55
import { Header } from '../common/Header';
66
import { Popup } from '../common/Popup';
77
import { useEvent } from '../../hooks/useEvent';
88
import { useWindowSize, type Size } from '../../hooks/env/useWindowSize';
9+
import { useBoolean } from '../../hooks/useBoolean';
910
import { clearCovered } from '../../actions/retro';
1011
import { archiveService } from '../../api/api';
1112
import { OPTIONS } from '../../helpers/optionManager';
@@ -37,12 +38,8 @@ const isSmallScreen = ({ width }: Size) => width <= 800;
3738
export const RetroPage = memo(
3839
({ retroToken, retro, retroDispatch, group }: PropsT) => {
3940
const smallScreen = useWindowSize(isSmallScreen);
40-
const [archivePopupVisible, setArchivePopupVisible] = useState(false);
41-
const showArchivePopup = useEvent(() => setArchivePopupVisible(true));
42-
const hideArchivePopup = useEvent(() => setArchivePopupVisible(false));
43-
const [invitePopupVisible, setInvitePopupVisible] = useState(false);
44-
const showInvitePopup = useEvent(() => setInvitePopupVisible(true));
45-
const hideInvitePopup = useEvent(() => setInvitePopupVisible(false));
41+
const archivePopupVisible = useBoolean(false);
42+
const invitePopupVisible = useBoolean(false);
4643

4744
const isArchiving = useRef(false);
4845
const performArchive = useEvent(() => {
@@ -56,7 +53,7 @@ export const RetroPage = memo(
5653
.then(() => {
5754
isArchiving.current = false;
5855
retroDispatch!(clearCovered());
59-
hideArchivePopup();
56+
archivePopupVisible.setFalse();
6057
})
6158
.catch((e) => {
6259
// TODO: report failure to user
@@ -76,14 +73,16 @@ export const RetroPage = memo(
7673
);
7774

7875
const links = [
79-
{ label: 'Invite', action: showInvitePopup },
76+
{ label: 'Invite', action: invitePopupVisible.setTrue },
8077
retroDispatch
8178
? {
8279
label: 'Settings',
8380
action: `/retros/${encodeURIComponent(retro.slug)}/settings`,
8481
}
8582
: null,
86-
canArchive ? { label: 'Create Archive', action: showArchivePopup } : null,
83+
canArchive
84+
? { label: 'Create Archive', action: archivePopupVisible.setTrue }
85+
: null,
8786
{
8887
label: 'Archives',
8988
action: `/retros/${encodeURIComponent(retro.slug)}/archives`,
@@ -112,28 +111,31 @@ export const RetroPage = memo(
112111
retroState={getState(group, retro)}
113112
group={group}
114113
dispatch={retroDispatch ?? undefined}
115-
onComplete={canArchive ? showArchivePopup : undefined}
114+
onComplete={canArchive ? archivePopupVisible.setTrue : undefined}
116115
archive={false}
117116
/>
118117
<Popup
119118
title="Create Archive"
120-
isOpen={Boolean(retroDispatch && archivePopupVisible)}
121-
keys={{ Enter: performArchive, Escape: hideArchivePopup }}
122-
onClose={hideArchivePopup}
119+
isOpen={Boolean(retroDispatch) && archivePopupVisible.value}
120+
keys={{ Enter: performArchive, Escape: archivePopupVisible.setFalse }}
121+
onClose={archivePopupVisible.setFalse}
123122
>
124123
<ArchivePopup
125124
onConfirm={performArchive}
126-
onCancel={hideArchivePopup}
125+
onCancel={archivePopupVisible.setFalse}
127126
/>
128127
</Popup>
129128
<Popup
130129
title="Invite"
131130
hideTitle
132-
isOpen={invitePopupVisible}
133-
keys={{ Enter: hideInvitePopup, Escape: hideInvitePopup }}
134-
onClose={hideInvitePopup}
131+
isOpen={invitePopupVisible.value}
132+
keys={{
133+
Enter: invitePopupVisible.setFalse,
134+
Escape: invitePopupVisible.setFalse,
135+
}}
136+
onClose={invitePopupVisible.setFalse}
135137
>
136-
<InvitePopup onClose={hideInvitePopup} />
138+
<InvitePopup onClose={invitePopupVisible.setFalse} />
137139
</Popup>
138140
</article>
139141
);

frontend/src/hooks/useBoolean.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { useState } from 'react';
2+
3+
export function useBoolean(initial: boolean) {
4+
const [value, setValue] = useState(initial);
5+
const [setters] = useState(() => ({
6+
setTrue: () => setValue(true),
7+
setFalse: () => setValue(false),
8+
}));
9+
return { value, setValue, ...setters };
10+
}

0 commit comments

Comments
 (0)