Skip to content

Commit 4200e46

Browse files
authored
Merge pull request #10953 from mikhail-fedosenko/feat/add-selection-namespaces
feat: use `storeKey` in useRecordSelection
2 parents a234afd + d91ca52 commit 4200e46

19 files changed

+961
-73
lines changed

docs/List.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ const Dashboard = () => (
486486
)
487487
```
488488

489-
Please note that the selection state is not synced in the URL but in a global store using the resource as key. Thus, all lists in the page using the same resource will share the same synced selection state. This is a design choice because if row selection is not tied to a resource, then when a user deletes a record it may remain selected without any ability to unselect it. If you want to allow custom `storeKey`'s for managing selection state, you will have to implement your own `useListController` hook and pass a custom key to the `useRecordSelection` hook. You will then need to implement your own `DeleteButton` and `BulkDeleteButton` to manually unselect rows when deleting records. You can still opt out of all store interactions including selection if you set it to `false`.
489+
Please note that the selection state is not synced in the URL but in a global store using the resource and, if provided, `storeKey` as part of the key. Thus, all lists in the page using the same resource and `storeKey` will share the same synced selection state. This is a design choice because if row selection is not tied to a resource, then when a user deletes a record it may remain selected without any ability to unselect it. You can still opt out of all store interactions for list state if you set it to `false`.
490490

491491
## `empty`
492492

@@ -1097,7 +1097,9 @@ const Admin = () => {
10971097

10981098
**Tip:** The `storeKey` is actually passed to the underlying `useListController` hook, which you can use directly for more complex scenarios. See the [`useListController` doc](./useListController.md#storekey) for more info.
10991099

1100-
**Note:** *Selection state* will remain linked to a resource-based key regardless of the specified `storeKey` string. This is a design choice because if row selection is not tied to a resource, then when a user deletes a record it may remain selected without any ability to unselect it. If you want to allow custom `storeKey`'s for managing selection state, you will have to implement your own `useListController` hook and pass a custom key to the `useRecordSelection` hook. You will then need to implement your own `DeleteButton` and `BulkDeleteButton` to manually unselect rows when deleting records. You can still opt out of all store interactions including selection if you set it to `false`.
1100+
**Tip:** The `storeKey` is also passed to the underlying `useRecordSelection` hook, so that lists with different storeKeys for same resource will have independent selection states.
1101+
1102+
**Tip:** Setting `storeKey` to `false` will opt out of all store interactions including selection.
11011103

11021104
## `title`
11031105

docs/useUnselect.md

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ title: "useUnselect"
55

66
# `useUnselect`
77

8-
This hook returns a function that unselects lines in the current `<DataTable>` that match an array of ids. Pass the name of the resource to the hook as argument.
8+
This hook returns a function that unselects lines in a `<DataTable>` that match an array of ids.
9+
10+
## Usage
911

1012
```jsx
1113
import { useListContext, useUnselect } from 'react-admin';
@@ -26,3 +28,109 @@ const UnselectButton = () => {
2628
};
2729
```
2830

31+
## Parameters
32+
33+
`useUnselect` accepts two parameters. Both are optional:
34+
35+
- [`resource`](#resource): The resource name. If not specified, the hook will only update the locally stored selection state (changes are not persisted in the Store).
36+
- [`storeKey`](#storekey): The store key to use. If not specified, the hook will derive the store key from the `resource`. It should match with the `storeKey` used in the parent `<List>`.
37+
38+
## `resource`
39+
40+
Use `resource` to specify the resource name.
41+
42+
```jsx
43+
import { useListContext, useUnselect } from 'react-admin';
44+
45+
const UnselectButton = () => {
46+
const { resource, selectedIds } = useListContext();
47+
const unselect = useUnselect(resource);
48+
49+
const handleClick = () => {
50+
unselect(selectedIds);
51+
};
52+
53+
return (
54+
<button onClick={handleClick}>
55+
{`Unselect ${selectedIds.length} records`}
56+
</button>
57+
);
58+
};
59+
```
60+
61+
If not specified, the hook will only update the locally stored selection state (changes are not persisted in the Store). This is notably useful when the parent `<List>` has the [`storeKey`](./List.md#storekey) prop set to `false`.
62+
63+
```jsx
64+
import { useListContext, useUnselect } from 'react-admin';
65+
66+
const UnselectButton = () => {
67+
const { selectedIds } = useListContext();
68+
// Call useUnselect without arguments - local selection only
69+
const unselect = useUnselect();
70+
71+
const handleClick = () => {
72+
unselect(selectedIds);
73+
};
74+
75+
return (
76+
<button onClick={handleClick}>
77+
{`Unselect ${selectedIds.length} records`}
78+
</button>
79+
);
80+
};
81+
```
82+
83+
## `storeKey`
84+
85+
The default store key is derived from the resource name: `${resource}.selectedIds`.
86+
87+
You can customize the store key used by passing a `storeKey` parameter to the hook. Make sure it matches the `storeKey` used in the parent `<List>`.
88+
89+
The final store key used will be `${storeKey}.selectedIds`.
90+
91+
```jsx
92+
import { useListContext, useUnselect } from 'react-admin';
93+
94+
const UnselectButton = () => {
95+
const { resource, selectedIds } = useListContext();
96+
const unselect = useUnselect(resource, 'customStoreKey');
97+
98+
const handleClick = () => {
99+
unselect(selectedIds);
100+
};
101+
102+
return (
103+
<button onClick={handleClick}>
104+
{`Unselect ${selectedIds.length} records`}
105+
</button>
106+
);
107+
};
108+
```
109+
110+
## Return value
111+
112+
`useUnselect` returns a function taking up to two parameters:
113+
114+
- `ids`: An array of record ids to unselect.
115+
- `fromAllStoreKeys`: A boolean indicating whether to unselect the records across all storeKeys used with this resource. Defaults to `false`. Set this to `true` for instance when the records are deleted, to ensure they don't remain selected in other lists.
116+
117+
```jsx
118+
import { useListContext, useUnselect } from 'react-admin';
119+
120+
const UnselectButton = () => {
121+
const { resource, selectedIds } = useListContext();
122+
const unselect = useUnselect(resource);
123+
124+
const handleClick = () => {
125+
// Unselect across all store keys
126+
unselect(selectedIds, true);
127+
};
128+
129+
return (
130+
<button onClick={handleClick}>
131+
{`Unselect ${selectedIds.length} records`}
132+
</button>
133+
);
134+
};
135+
```
136+

docs/useUnselectAll.md

Lines changed: 97 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,109 @@ title: "useUnselectAll"
55

66
# `useUnselectAll`
77

8-
This hook returns a function that unselects all lines in the current `<DataTable>`. Pass the name of the resource as argument.
8+
This hook returns a function that unselects all lines in a `<DataTable>`.
9+
10+
## Usage
11+
12+
```jsx
13+
import { useListContext, useUnselectAll } from 'react-admin';
14+
15+
const UnselectAllButton = () => {
16+
const { resource } = useListContext();
17+
const unselectAll = useUnselectAll(resource);
18+
19+
const handleClick = () => {
20+
unselectAll();
21+
};
22+
23+
return <button onClick={handleClick}>Unselect all</button>;
24+
};
25+
```
26+
27+
## Parameters
28+
29+
`useUnselectAll` accepts two parameters. Both are optional:
30+
31+
- [`resource`](#resource): The resource name. If not specified, the hook will only update the locally stored selection state (changes are not persisted in the Store).
32+
- [`storeKey`](#storekey): The store key to use. If not specified, the hook will derive the store key from the `resource`. It should match with the `storeKey` used in the parent `<List>`.
33+
34+
## `resource`
35+
36+
Use `resource` to specify the resource name.
937

1038
```jsx
11-
import { useUnselectAll } from 'react-admin';
39+
import { useListContext, useUnselectAll } from 'react-admin';
1240

1341
const UnselectAllButton = () => {
14-
const unselectAll = useUnselectAll('posts');
42+
const { resource } = useListContext();
43+
const unselectAll = useUnselectAll(resource);
44+
45+
const handleClick = () => {
46+
unselectAll();
47+
};
48+
49+
return <button onClick={handleClick}>Unselect all</button>;
50+
};
51+
```
52+
53+
If not specified, the hook will only update the locally stored selection state (changes are not persisted in the Store). This is notably useful when the parent `<List>` has the [`storeKey`](./List.md#storekey) prop set to `false`.
54+
55+
```jsx
56+
import { useListContext, useUnselectAll } from 'react-admin';
57+
58+
const UnselectAllButton = () => {
59+
// Call useUnselectAll without arguments - local selection only
60+
const unselectAll = useUnselectAll();
61+
1562
const handleClick = () => {
1663
unselectAll();
17-
}
64+
};
65+
66+
return <button onClick={handleClick}>Unselect all</button>;
67+
};
68+
```
69+
70+
## `storeKey`
71+
72+
The default store key is derived from the resource name: `${resource}.selectedIds`.
73+
74+
You can customize the store key used by passing a `storeKey` parameter to the hook. Make sure it matches the `storeKey` used in the parent `<List>`.
75+
76+
The final store key used will be `${storeKey}.selectedIds`.
77+
78+
```jsx
79+
import { useListContext, useUnselectAll } from 'react-admin';
80+
81+
const UnselectAllButton = () => {
82+
const { resource } = useListContext();
83+
const unselectAll = useUnselectAll(resource, 'customStoreKey');
84+
85+
const handleClick = () => {
86+
unselectAll();
87+
};
88+
89+
return <button onClick={handleClick}>Unselect all</button>;
90+
};
91+
```
92+
93+
## Return value
94+
95+
`useUnselectAll` returns a function taking one optional parameter:
96+
97+
- `fromAllStoreKeys`: A boolean indicating whether to unselect the records across all storeKeys used with this resource. Defaults to `false`. Set this to `true` for instance when the records are deleted, to ensure they don't remain selected in other lists.
98+
99+
```jsx
100+
import { useListContext, useUnselectAll } from 'react-admin';
101+
102+
const UnselectAllButton = () => {
103+
const { resource } = useListContext();
104+
const unselectAll = useUnselectAll(resource);
105+
106+
const handleClick = () => {
107+
// Unselect across all store keys
108+
unselectAll(true);
109+
};
110+
18111
return <button onClick={handleClick}>Unselect all</button>;
19112
};
20113
```

docs_headless/src/content/docs/useUnselect.md

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
title: "useUnselect"
33
---
44

5-
This hook returns a function that unselects lines in the current data table (see `<DataTableBase>`) that match an array of ids. Pass the name of the resource to the hook as argument.
5+
This hook returns a function that unselects lines in a data table (see `<DataTableBase>`) that match an array of ids.
6+
7+
## Usage
68

79
```jsx
810
import { useListContext, useUnselect } from 'ra-core';
@@ -23,3 +25,109 @@ const UnselectButton = () => {
2325
};
2426
```
2527

28+
## Parameters
29+
30+
`useUnselect` accepts two parameters. Both are optional:
31+
32+
- [`resource`](#resource): The resource name. If not specified, the hook will only update the locally stored selection state (changes are not persisted in the Store).
33+
- [`storeKey`](#storekey): The store key to use. If not specified, the hook will derive the store key from the `resource`. It should match the `storeKey` used by the parent controller (e.g. `useListController` or `<ListBase>`).
34+
35+
## `resource`
36+
37+
Use `resource` to specify the resource name.
38+
39+
```jsx
40+
import { useListContext, useUnselect } from 'ra-core';
41+
42+
const UnselectButton = () => {
43+
const { resource, selectedIds } = useListContext();
44+
const unselect = useUnselect(resource);
45+
46+
const handleClick = () => {
47+
unselect(selectedIds);
48+
};
49+
50+
return (
51+
<button onClick={handleClick}>
52+
{`Unselect ${selectedIds.length} records`}
53+
</button>
54+
);
55+
};
56+
```
57+
58+
If not specified, the hook will only update the locally stored selection state (changes are not persisted in the Store). This is notably useful when the parent list has the [`storeKey`](./ListBase.md#storekey) prop set to `false`.
59+
60+
```jsx
61+
import { useListContext, useUnselect } from 'ra-core';
62+
63+
const UnselectButton = () => {
64+
const { selectedIds } = useListContext();
65+
// Call useUnselect without arguments - local selection only
66+
const unselect = useUnselect();
67+
68+
const handleClick = () => {
69+
unselect(selectedIds);
70+
};
71+
72+
return (
73+
<button onClick={handleClick}>
74+
{`Unselect ${selectedIds.length} records`}
75+
</button>
76+
);
77+
};
78+
```
79+
80+
## `storeKey`
81+
82+
The default store key is derived from the resource name: `${resource}.selectedIds`.
83+
84+
You can customize the store key used by passing a `storeKey` parameter to the hook. Make sure it matches the `storeKey` used in the controller (`useListController` or `<ListBase>`).
85+
86+
The final store key used will be `${storeKey}.selectedIds`.
87+
88+
```jsx
89+
import { useListContext, useUnselect } from 'ra-core';
90+
91+
const UnselectButton = () => {
92+
const { resource, selectedIds } = useListContext();
93+
const unselect = useUnselect(resource, 'customStoreKey');
94+
95+
const handleClick = () => {
96+
unselect(selectedIds);
97+
};
98+
99+
return (
100+
<button onClick={handleClick}>
101+
{`Unselect ${selectedIds.length} records`}
102+
</button>
103+
);
104+
};
105+
```
106+
107+
## Return value
108+
109+
`useUnselect` returns a function taking up to two parameters:
110+
111+
- `ids`: An array of record ids to unselect.
112+
- `fromAllStoreKeys`: A boolean indicating whether to unselect the records across all storeKeys used with this resource. Defaults to `false`. Set this to `true` for instance when the records are deleted, to ensure they don't remain selected in other lists.
113+
114+
```jsx
115+
import { useListContext, useUnselect } from 'ra-core';
116+
117+
const UnselectButton = () => {
118+
const { resource, selectedIds } = useListContext();
119+
const unselect = useUnselect(resource);
120+
121+
const handleClick = () => {
122+
// Unselect across all store keys
123+
unselect(selectedIds, true);
124+
};
125+
126+
return (
127+
<button onClick={handleClick}>
128+
{`Unselect ${selectedIds.length} records`}
129+
</button>
130+
);
131+
};
132+
```
133+

0 commit comments

Comments
 (0)