0

我想在页面中实现这个结构:
1. 带有摘要的卡片(收入、用户等)
2. 来自谷歌地图的地图
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 组件中使用的过滤器。

我将如何实现这一目标?

4

2 回答 2

3

谢谢!我会知道如何连接新动作。但是我不知道如何连接到已使用的操作以将过滤器选项传递给 Maps 和 AnyComponent,因此我可以在那里显示相关信息,这些信息应该在列表组件中触发过滤器后更新其状态。

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

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

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

引用自admin-on-rest文档:

Admin-on-rest 在构建时考虑了定制。您可以将任何 admin-on-rest 组件替换为您自己的组件,例如显示自定义列表布局或给定资源的不同版本表单。

如果您只想在列表视图中显示其他元素,则可以包装<List>组件而不是<Resource>组件。该<List>组件接收道具“数据”中的实体和道具“ids”中的过滤ID。您可以使用它在您自己的组件中显示它。例如,如果您想管理位置列表并在列表组件中显示谷歌地图:

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>,并且它将使用新位置重新呈现。但请记住,这只会在管理页面的列表视图中显示您的谷歌地图。

2. 将您的组件连接到 redux 商店。

仅当您希望您的组件(例如 google 地图)显示在列表视图之外时才执行此操作。这个要高级得多,因为您需要更多地了解admin-on-rest. 您必须将自定义组件连接到 redux 商店。您可以使用包中的connect()功能来做到这一点react-redux

// 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是一个函数,它获取商店中的当前状态和组件的 props,并返回一个包含要传递给组件的附加 props 的对象。

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

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

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

于 2017-07-08T15:18:39.937 回答
0

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);
于 2017-07-03T15:27:31.170 回答