如何取消选择 React 管理员自定义批量操作按钮中的列表项
我有一个 React 管理项目,并为传递到
bulkActionButtons
属性的列表视图实现了一个自定义按钮,如下面文档所述:
https://marmelab.com/react-admin/List.html#bulk-action-buttons
const BulkUserActions = props => (
<MakeAdminButton {...props}/>
);
const UserList = props => (
<List {...props} bulkActionButtons={<BulkUserActions/>}>
<Datagrid rowClick="show">
<TextField source="id"/>
<EmailField source="email"/>
</Datagrid>
</List>
);
MakeAdminButton
处理点击并执行我需要的更新。难题中缺少的部分是如何在操作完成后取消选择列表项。
props.selectedIds
受到保护,因此在完成我的逻辑后,我无法简单地将其设置为空数组。
问题是如何取消设置
props.selectedIds
或在完成后取消选择列表项的其他方法。
const MakeAdminButton = withStyles(styles)(class MakeAdminButton extends React.Component {
handleAction = () => {
//does the stuff as required using this.props.selectedIds
//what to return to unset this.props.selectedIds
};
render () {
return <Button variant="contained"
color="primary"
onClick={this.handleAction}
<AdminIcon/>
</Button>;
}
});
React Admin 提供了实现此目的的方法。在 v3 上直接使用 useUnselectAll 或在 useMutation、useUpdateMany 和 useDataProvider 钩子的 onSuccess 回调上。在 v2 中使用 withDataProvider 装饰器的 dataProvider 第四个参数或将自定义 redux 操作的 meta.onSuccess.unselectAll 设置为 true,或者使用 crudUpdateMany 自动设置,或者使用 Mutation 组件的 options prop。
对于带有 crudUpdateMany 的 v2,
转到
Mike Miller 的回答。
工作示例:
https://codesandbox.io/s/exciting-firefly-dd1ni?file=/src/App.js
v3:
const UnselectAllButtonV3Hook = props => {
const unselectAll = useUnselectAll();
return (
<Button
onClick={() => {
unselectAll(props.resource);
}}
>
Unselect all with v3 hook
</Button>
);
};
https://marmelab.com/react-admin/doc/3.5/Actions.html#handling-side-effects-in-usedataprovider
useUpdateMany/useDataProvider/useMutation 钩子,onSuccess 回调从
useUnselectAll()
调用
unselectAll()
const MakeAdminButtonV3 = props => {
const refresh = useRefresh();
const unselectAll = useUnselectAll();
const [makeAdmin, { loading }] = useUpdateMany(
props.resource,
props.selectedIds,
{ isAdmin: true },
{
onSuccess: () => {
unselectAll(props.resource);
refresh();
}
}
);
//OR
const dataProvider = useDataProvider();
const makeAdmin2 = () => {
dataProvider.updateMany(
props.resource,
{ ids: props.selectedIds, data: { isAdmin: true } },
{
onSuccess: () => {
unselectAll(props.resource);
refresh();
}
}
);
};
//OR
const [makeAdmin3, { loading3 }] = useMutation(
{
type: "updateMany",
resource: props.resource,
payload: { ids: props.selectedIds, data: { isAdmin: true } }
},
{
onSuccess: () => {
unselectAll(props.resource);
refresh();
}
}
);
return (
<Button onClick={makeAdmin3} disabled={loading3}>
Make Admin with V3 dataProvider hooks
</Button>
);
};
https://marmelab.com/react-admin/doc/3.5/Actions.html#usemutation-hook
https://marmelab.com/react-admin/doc/3.5/Actions.html#usedataprovider-hook
https://marmelab.com/react-admin/doc/3.5/Actions.html#specialized-hooks
V2 示例也适用于 v3,但 Mutation 和 withDataProvider 是遗留的,在使用 dataProvider 时有细微的变化直接,因为 v3 上的 dataProvider api 已更改。
v2:
withDataProvider:
const UnmakeAdminButtonWithWithDataProvider = withDataProvider(
class extends React.Component {
handleClick = () => {
this.props.dataProvider(
UPDATE_MANY,
"users",
{ ids: this.props.selectedIds, data: { isAdmin: false } },
{ onSuccess: { unselectAll: true, refresh: true } }
);
};
render() {
return (
<Button onClick={this.handleClick}>
Unmake Admin with withDataProvider
</Button>
);
}
}
);
https://marmelab.com/react-admin/doc/2.9/Actions.html#handling-side-effects
自定义 redux 操作:
import { connect } from 'react-redux';
const MAKE_ADMIN = "MAKE_ADMIN";
const makeAdmin = ids => ({
type: MAKE_ADMIN,
payload: { ids, data: { isAdmin: true } },
meta: {
fetch: UPDATE_MANY,
resource: "users",
onSuccess: { unselectAll: true, refresh: true }
}
});
const MakeAdminButtonWithCustomAction = connect(
null,
{ makeAdmin }
)(
class extends React.Component {
handleClick = () => {
this.props.makeAdmin(this.props.selectedIds);
};
render() {
return (
<Button onClick={this.handleClick}>
Make Admin With Custom Redux Action
</Button>
);
}
}
);
https://marmelab.com/react-admin/doc/2.9/Actions.html#adding-side-effects-to-actions
突变组件:
const MakeAdminMutationV2 = props => (
<Mutation
type="updateMany" //{UPDATE_MANY}
resource={props.resource}
payload={{ ids: props.selectedIds, data: { isAdmin: true } }}
options={{
onSuccess: {
unselectAll: true,
refresh: true
}
}}
>
{approve => <Button onClick={approve}>Make admin with Mutation</Button>}
</Mutation>
);
https://marmelab.com/react-admin/doc/2.9/Actions.html#query-and-mutation-components
每次单击复选框时设置一些元数据,以便它将 true 或 false 注入数组,例如:
listData = {
...
isChecked : true
}
然后在处理批量操作的函数内部,添加一个
[listData].filter()
,(lodash 过滤器速度更快),以检查并查看哪个
isChecked === true
,然后将它们设置为 false,并更新复选框输入标签上的
value={bool
属性。
解决方案是从 react admin 调用批量辅助函数:
class MakeAdminButton extends React.Component {
handleAction = () => {
const { basePath, crudUpdateMany, resource, selectedIds } = this.props;
//custom code goes in here...
//calling this function triggers the unset and closes the toolbar
crudUpdateMany(resource, selectedIds, { isAdmin: true }, basePath);
};
render () {
return <Button label="Make Admin" onClick={this.handleAction}>
<AdminIcon/>
</Button>;
}
};
const BulkUserActions = connect(undefined, { crudUpdateMany })(MakeAdminButton);
const UserList = props => (
<List {...props} bulkActionButtons={<BulkUserActions/>}>
<Datagrid>
<TextField source="id"/>
<EmailField source="email"/>
<BooleanField source="isAdmin" label="Admin" />
</Datagrid>
</List>
);
如果我仔细阅读的话,此页面上会显示一个示例: https://github.com/marmelab/react-admin/blob/master/docs/List.md#bulk-action-buttons