Admin-on-rest - 如何将其他组件与从 List 过滤的查询同步?

Admin-on-rest - how to sync other components with query filtered from List?

我想在页面中实现这个结构:
1.带有摘要的卡片(收入、用户等)
2. 地图来自google maps
3.列表元素

List 元素内部有过滤。我不知道如何在过滤列表时使用用户过滤选项来表示地图和卡片中的过滤信息。

正如@trixn 所推荐的,我正在使用这个结构:

// app.js

<Admin restClient={jsonServerRestClient('http://jsonplaceholder.typicode.com')}>
    <Resource name="posts" list={MyCustomPostList} /* other views */ />
</Admin>


// MyCustomPostList.js
class MyCustomPostList extends React.Component {
render() {
    const {myOwnProp, ...otherProps} = this.props;

    return (
        <div>
            // render your own components here
            <AnyComponent myOwnProp={myOwnProp} />
            <AGoogleMapsComponent />

            // render the normal <List> component
            <List {...otherProps}>
                <Datagrid>
                    <TextField source="id" />
                    <TextField source="title" />
                    <TextField source="body" />
                </Datagrid>
             </List>
        </div>
    );
}
}

现在我无法将所需数据发送到 Maps 和 AnyComponent。 因此,我要么必须将相同的数据传递给 Maps 和 AnyComponent,要么以某种方式同步 List 组件中使用的过滤器。

我该如何实现?

admin-on-rest 导出的List 组件与redux 连接,接收state 的过滤器。你也应该这样做。查看List组件的代码,特别是mapStateToProps函数:

admin-on-rest 导出的List 组件与redux 连接,接收state 的过滤器。你也应该这样做。查看List组件的代码,特别是mapStateToProps函数:

类似于:

// MyCustomPostList.js
import { connect } from 'react-redux';
import { parse } from 'query-string';

class MyCustomPostList extends React.Component {
    render() {
        const { myOwnProp, query: { filter }, ...otherProps } = this.props;

        return (
            <div>
                // render your own components here
                <AnyComponent filter={filter} myOwnProp={myOwnProp} />
                <AGoogleMapsComponent filter={filter} />

                // render the normal <List> component
                <List {...otherProps}>
                    <Datagrid>
                        <TextField source="id" />
                        <TextField source="title" />
                        <TextField source="body" />
                    </Datagrid>
                </List>
            </div>
        );
    }
}

const getLocationSearch = props => props.location.search;
const getQuery = createSelector(
    getLocationSearch,
    (locationSearch) => {
        const query = parse(locationSearch);
        if (query.filter && typeof query.filter === 'string') {
            query.filter = JSON.parse(query.filter);
        }
        return query;
    },
);

function mapStateToProps(state, props) {
    return {
        query: getQuery(props),
    };
}

export default connect(mapStateToProps)(MyCustomPostList);

Thank you! I would know how to connect new actions. But I am lost how to connect to already used actions to pass Filter options to Maps and AnyComponent, so I could show relevant information there, which should update its state after Filters are being triggered in List component.

您没有连接到操作。你分派它们来改变 redux store 的状态。完全理解 redux 的概念很重要,否则你将很难构建这种自定义应用程序。为了确保数据只从上到下流动,组件只能监听商店的变化,而不是行动。

所以基本上你有两个选择:

1.创建您自己的 <List> 组件

引自 admin-on-rest 文档:

Admin-on-rest was build with customization in mind. You can replace any admin-on-rest component with a component of your own, for instance to display a custom list layout, or a different edition form for a given resource.

如果您只想在列表视图中显示额外的元素,您可以包装 <List> 组件而不是 <Resource> 组件。 <List> 组件接收 prop "data" 中的实体和 prop "ids" 中的过滤 ID。您可以使用它在您自己的组件中显示它。例如。如果您想管理位置列表并在列表组件中显示 google 地图:

import React from 'react';
import { List } from 'admin-on-rest';


const LocationsList = props => (
    // render your own components
    <MyGoogleMapsComponent  data={this.props.data} ids={this.props.ids}>

    // render the admin-on-rest <List> component
    <List {...props}>
        // render the DataGrid
    </List>
);

然后您可以将自定义列表传递给 <Resource> 组件:

<Admin>
    <Resource name="locations" list={LocationList} />
</Admin>

当您在列表中过滤您的位置时,更新的查询将传递给您的 <LocationList> 并且它将使用新位置重新呈现。但请记住,这只会在您的管理页面的列表视图中显示您的 google 地图。

2。将您的组件连接到 redux 存储。

仅当您需要您的组件时才这样做,例如google 地图,显示在列表视图之外。这个要高级得多,因为您需要了解更多关于 admin-on-rest 的内部知识。您必须将自定义组件连接到 redux 存储。您可以使用 react-redux 包中的 connect() 函数来做到这一点:

// in MyGoogleMapsComponent.js
import React from 'react';
import { connect } from 'react-redux';

const LocationMap = ({locations}) => (
    //render something based on the props
);

const mapStateToProps = (state, props) => {
    // state.admin contains all the registered resources with their name as a key
    const locationsResource = state.admin.locations;

    // every resource has a "data" object with all entities mapped by id
    const allLocations = locationsResource.data;        

    // every resource has a "list" object that has an array of ids of the currently filtered entities
    const filteredIDs = locationsResource.list.ids;

    return {
        locations: filteredIDs.map(id => allLocations[id]),
    };
};

// connect your component to the store
export default connect(mapStateToProps)(LocationsList)

mapStateToProps 是一个函数,它获取商店中的当前状态和组件的道具,returns 一个包含要传递给组件的附加道具的对象。

此方法还使用了 admin-on-rest 组件实现的内部结构。您需要使用的一些道具不是 api 的一部分,并且在最坏的情况下可能会突然改变,在这种情况下,如果您更新到 admin-on-rest 的新版本,您的应用可能无法再工作.所以请记住,当发生重大更改时,您可能需要更新您的实现。

如果您只想访问过滤器本身,它们存储在 yourResourceName.list.params.filter 下的每个资源中,过滤器的名称作为键,值作为值...

提示: 如果您想了解 admin-on-rest 应用商店中的数据如何存储在现实生活中的示例中,请安装 Redux DevTools for google chrome and open the admin-on-rest demo .然后您可以打开检查栏,将有一个新的选项卡 redux,您可以在其中查看 redux 存储的内容以及与应用程序交互时分派的所有操作。通过这种方式,您将更容易理解 admin-on-rest 的工作原理。