Skip to content

Commit 1954709

Browse files
authored
Wrap all the makeActions functions in useCallback (#2112)
wrap all the makeActions functions in useCallback
1 parent 4db8d83 commit 1954709

File tree

16 files changed

+285
-248
lines changed

16 files changed

+285
-248
lines changed

app/pages/ProjectsPage.tsx

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8-
import { useMemo } from 'react'
8+
import { useCallback, useMemo } from 'react'
99
import { Link, Outlet, useNavigate } from 'react-router-dom'
1010

1111
import {
@@ -62,28 +62,31 @@ export function ProjectsPage() {
6262
},
6363
})
6464

65-
const makeActions = (project: Project): MenuAction[] => [
66-
{
67-
label: 'Edit',
68-
onActivate: () => {
69-
// the edit view has its own loader, but we can make the modal open
70-
// instantaneously by preloading the fetch result
71-
apiQueryClient.setQueryData(
72-
'projectView',
73-
{ path: { project: project.name } },
74-
project
75-
)
76-
navigate(pb.projectEdit({ project: project.name }))
65+
const makeActions = useCallback(
66+
(project: Project): MenuAction[] => [
67+
{
68+
label: 'Edit',
69+
onActivate: () => {
70+
// the edit view has its own loader, but we can make the modal open
71+
// instantaneously by preloading the fetch result
72+
apiQueryClient.setQueryData(
73+
'projectView',
74+
{ path: { project: project.name } },
75+
project
76+
)
77+
navigate(pb.projectEdit({ project: project.name }))
78+
},
7779
},
78-
},
79-
{
80-
label: 'Delete',
81-
onActivate: confirmDelete({
82-
doDelete: () => deleteProject.mutateAsync({ path: { project: project.name } }),
83-
label: project.name,
84-
}),
85-
},
86-
]
80+
{
81+
label: 'Delete',
82+
onActivate: confirmDelete({
83+
doDelete: () => deleteProject.mutateAsync({ path: { project: project.name } }),
84+
label: project.name,
85+
}),
86+
},
87+
],
88+
[deleteProject, navigate]
89+
)
8790

8891
useQuickActions(
8992
useMemo(

app/pages/project/disks/DisksPage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { DateCell } from '~/table/cells/DateCell'
2626
import { InstanceLinkCell } from '~/table/cells/InstanceLinkCell'
2727
import { SizeCell } from '~/table/cells/SizeCell'
2828
import { useColsWithActions, type MenuAction } from '~/table/columns/action-col'
29-
import { useQueryTable2 } from '~/table/QueryTable2'
29+
import { useQueryTable } from '~/table/QueryTable2'
3030
import { buttonStyle } from '~/ui/lib/Button'
3131
import { EmptyMessage } from '~/ui/lib/EmptyMessage'
3232
import { PageHeader, PageTitle } from '~/ui/lib/PageHeader'
@@ -97,7 +97,7 @@ const staticCols = [
9797
export function DisksPage() {
9898
const queryClient = useApiQueryClient()
9999
const { project } = useProjectSelector()
100-
const { Table } = useQueryTable2('diskList', { query: { project } })
100+
const { Table } = useQueryTable('diskList', { query: { project } })
101101
const addToast = useToast()
102102

103103
const deleteDisk = useApiMutation('diskDelete', {

app/pages/project/floating-ips/FloatingIpsPage.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import { addToast } from '~/stores/toast'
2929
import { InstanceLinkCell } from '~/table/cells/InstanceLinkCell'
3030
import { makeLinkCell } from '~/table/cells/LinkCell'
3131
import { useColsWithActions, type MenuAction } from '~/table/columns/action-col'
32-
import { useQueryTable2 } from '~/table/QueryTable2'
32+
import { useQueryTable } from '~/table/QueryTable2'
3333
import { EmptyMessage } from '~/ui/lib/EmptyMessage'
3434
import { Listbox } from '~/ui/lib/Listbox'
3535
import { Message } from '~/ui/lib/Message'
@@ -180,7 +180,7 @@ export function FloatingIpsPage() {
180180
[deleteFloatingIp, floatingIpDetach, navigate, project, instances]
181181
)
182182

183-
const { Table } = useQueryTable2('floatingIpList', { query: { project } })
183+
const { Table } = useQueryTable('floatingIpList', { query: { project } })
184184

185185
const columns = useColsWithActions(staticCols, makeActions)
186186

app/pages/project/images/ImagesPage.tsx

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8-
import { useState } from 'react'
8+
import { useCallback, useState } from 'react'
99
import { Link, Outlet, type LoaderFunctionArgs } from 'react-router-dom'
1010

1111
import { apiQueryClient, useApiMutation, useApiQueryClient, type Image } from '@oxide/api'
@@ -59,20 +59,26 @@ export function ImagesPage() {
5959
},
6060
})
6161

62-
const makeActions = (image: Image): MenuAction[] => [
63-
{
64-
label: 'Promote',
65-
onActivate: () => setPromoteImageName(image.name),
66-
},
67-
{
68-
label: 'Delete',
69-
onActivate: confirmDelete({
70-
doDelete: () =>
71-
deleteImage.mutateAsync({ path: { image: image.name }, query: projectSelector }),
72-
label: image.name,
73-
}),
74-
},
75-
]
62+
const makeActions = useCallback(
63+
(image: Image): MenuAction[] => [
64+
{
65+
label: 'Promote',
66+
onActivate: () => setPromoteImageName(image.name),
67+
},
68+
{
69+
label: 'Delete',
70+
onActivate: confirmDelete({
71+
doDelete: () =>
72+
deleteImage.mutateAsync({
73+
path: { image: image.name },
74+
query: projectSelector,
75+
}),
76+
label: image.name,
77+
}),
78+
},
79+
],
80+
[deleteImage, projectSelector]
81+
)
7682

7783
return (
7884
<>

app/pages/project/instances/instance/tabs/NetworkingTab.tsx

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8-
import { useState } from 'react'
8+
import { useCallback, useState } from 'react'
99
import { type LoaderFunctionArgs } from 'react-router-dom'
1010

1111
import {
@@ -122,48 +122,55 @@ export function NetworkingTab() {
122122
})
123123
const canUpdateNic = instanceCan.updateNic(instance)
124124

125-
const makeActions = (nic: InstanceNetworkInterface): MenuAction[] => [
126-
{
127-
label: 'Make primary',
128-
onActivate() {
129-
editNic.mutate({
130-
path: { interface: nic.name },
131-
query: instanceSelector,
132-
body: { ...nic, primary: true },
133-
})
125+
const makeActions = useCallback(
126+
(nic: InstanceNetworkInterface): MenuAction[] => [
127+
{
128+
label: 'Make primary',
129+
onActivate() {
130+
editNic.mutate({
131+
path: { interface: nic.name },
132+
query: instanceSelector,
133+
body: { ...nic, primary: true },
134+
})
135+
},
136+
disabled: nic.primary
137+
? 'This network interface is already set as primary'
138+
: !canUpdateNic && (
139+
<>
140+
The instance must be {updateNicStates} to change its primary network
141+
interface
142+
</>
143+
),
134144
},
135-
disabled: nic.primary
136-
? 'This network interface is already set as primary'
137-
: !canUpdateNic && (
138-
<>
139-
The instance must be {updateNicStates} to change its primary network interface
140-
</>
141-
),
142-
},
143-
{
144-
label: 'Edit',
145-
onActivate() {
146-
setEditing(nic)
145+
{
146+
label: 'Edit',
147+
onActivate() {
148+
setEditing(nic)
149+
},
150+
disabled: !canUpdateNic && (
151+
<>
152+
The instance must be {updateNicStates} before editing a network interface&apos;s
153+
settings
154+
</>
155+
),
147156
},
148-
disabled: !canUpdateNic && (
149-
<>
150-
The instance must be {updateNicStates} before editing a network interface&apos;s
151-
settings
152-
</>
153-
),
154-
},
155-
{
156-
label: 'Delete',
157-
onActivate: confirmDelete({
158-
doDelete: () =>
159-
deleteNic.mutateAsync({ path: { interface: nic.name }, query: instanceSelector }),
160-
label: nic.name,
161-
}),
162-
disabled: !canUpdateNic && (
163-
<>The instance must be {updateNicStates} to delete a network interface</>
164-
),
165-
},
166-
]
157+
{
158+
label: 'Delete',
159+
onActivate: confirmDelete({
160+
doDelete: () =>
161+
deleteNic.mutateAsync({
162+
path: { interface: nic.name },
163+
query: instanceSelector,
164+
}),
165+
label: nic.name,
166+
}),
167+
disabled: !canUpdateNic && (
168+
<>The instance must be {updateNicStates} to delete a network interface</>
169+
),
170+
},
171+
],
172+
[canUpdateNic, deleteNic, editNic, instanceSelector]
173+
)
167174

168175
const emptyState = (
169176
<EmptyMessage

app/pages/project/snapshots/SnapshotsPage.tsx

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8+
import { useCallback } from 'react'
89
import { Link, Outlet, useNavigate, type LoaderFunctionArgs } from 'react-router-dom'
910

1011
import {
@@ -81,8 +82,8 @@ SnapshotsPage.loader = async ({ params }: LoaderFunctionArgs) => {
8182

8283
export function SnapshotsPage() {
8384
const queryClient = useApiQueryClient()
84-
const projectSelector = useProjectSelector()
85-
const { Table, Column } = useQueryTable('snapshotList', { query: projectSelector })
85+
const { project } = useProjectSelector()
86+
const { Table, Column } = useQueryTable('snapshotList', { query: { project } })
8687
const navigate = useNavigate()
8788

8889
const deleteSnapshot = useApiMutation('snapshotDelete', {
@@ -91,33 +92,35 @@ export function SnapshotsPage() {
9192
},
9293
})
9394

94-
const makeActions = (snapshot: Snapshot): MenuAction[] => [
95-
{
96-
label: 'Create image',
97-
onActivate() {
98-
navigate(pb.snapshotImagesNew({ ...projectSelector, snapshot: snapshot.name }))
95+
const makeActions = useCallback(
96+
(snapshot: Snapshot): MenuAction[] => [
97+
{
98+
label: 'Create image',
99+
onActivate() {
100+
navigate(pb.snapshotImagesNew({ project, snapshot: snapshot.name }))
101+
},
99102
},
100-
},
101-
{
102-
label: 'Delete',
103-
onActivate: confirmDelete({
104-
doDelete: () =>
105-
deleteSnapshot.mutateAsync({
106-
path: { snapshot: snapshot.name },
107-
query: projectSelector,
108-
}),
109-
label: snapshot.name,
110-
}),
111-
},
112-
]
113-
103+
{
104+
label: 'Delete',
105+
onActivate: confirmDelete({
106+
doDelete: () =>
107+
deleteSnapshot.mutateAsync({
108+
path: { snapshot: snapshot.name },
109+
query: { project },
110+
}),
111+
label: snapshot.name,
112+
}),
113+
},
114+
],
115+
[deleteSnapshot, navigate, project]
116+
)
114117
return (
115118
<>
116119
<PageHeader>
117120
<PageTitle icon={<Snapshots24Icon />}>Snapshots</PageTitle>
118121
</PageHeader>
119122
<TableActions>
120-
<Link to={pb.snapshotsNew(projectSelector)} className={buttonStyle({ size: 'sm' })}>
123+
<Link to={pb.snapshotsNew({ project })} className={buttonStyle({ size: 'sm' })}>
121124
New Snapshot
122125
</Link>
123126
</TableActions>

app/pages/project/vpcs/VpcPage/tabs/VpcSubnetsTab.tsx

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright Oxide Computer Company
77
*/
8-
import { useState } from 'react'
8+
import { useCallback, useState } from 'react'
99

1010
import { useApiMutation, useApiQueryClient, type VpcSubnet } from '@oxide/api'
1111

@@ -34,20 +34,23 @@ export const VpcSubnetsTab = () => {
3434
},
3535
})
3636

37-
const makeActions = (subnet: VpcSubnet): MenuAction[] => [
38-
{
39-
label: 'Edit',
40-
onActivate: () => setEditing(subnet),
41-
},
42-
// TODO: only show if you have permission to do this
43-
{
44-
label: 'Delete',
45-
onActivate: confirmDelete({
46-
doDelete: () => deleteSubnet.mutateAsync({ path: { subnet: subnet.id } }),
47-
label: subnet.name,
48-
}),
49-
},
50-
]
37+
const makeActions = useCallback(
38+
(subnet: VpcSubnet): MenuAction[] => [
39+
{
40+
label: 'Edit',
41+
onActivate: () => setEditing(subnet),
42+
},
43+
// TODO: only show if you have permission to do this
44+
{
45+
label: 'Delete',
46+
onActivate: confirmDelete({
47+
doDelete: () => deleteSubnet.mutateAsync({ path: { subnet: subnet.id } }),
48+
label: subnet.name,
49+
}),
50+
},
51+
],
52+
[deleteSubnet]
53+
)
5154

5255
const emptyState = (
5356
<EmptyMessage

0 commit comments

Comments
 (0)