-->

Use on React-Admin dashboard

2020-07-09 07:55发布

问题:

I'm using react-admin v2.3.2 with a custom dashboard component as shown in the react-admin tutorial.

    <Admin dashboard={MyDashboard}>
       <Resource name="incidents ... />
    </Admin>

Now I'd like to display a list of incidents on my dashboard using the component of react-admin but react-admin complains about missing properties like 'hasEdit'.

I simply passed the props of the dashboard component to the List but this does obviously not work:

    class MyDashboard extends React.Component    {
      constructor(props) {
      super(props)

      render(
        return <List {...this.props}>
          <Datagrid> .... </Datagrid>
        </List>

      )
    }

Is it possible to use react-admin's <List /> component on the dashboard and if so how can this be done?

Thanks in advance, Thomas

回答1:

I finally managed to use react-admin's components by faking the required props. Within the MyDashboard component I define props required by the component:

    let fakeProps = {
        basePath: "/incidents",
        hasCreate: false,
        hasEdit: false,
        hasList: true,
        hasShow: false,
        history: {},
        location: { pathname: "/", search: "", hash: "", state: undefined },
        match: { path: "/", url: "/", isExact: true, params: {} },
        options: {},
        permissions: null,
        resource: "incidents"
    }

    <List {...fakeProps}>
      <DataGrid>
        <TextField .... />
      </DataGrid>
    </List>

This is indeed a sub-optimal solution but in the first run it solves my problem.



回答2:

We had a request to create a List in the Dashboard so I had use the accepted answer. Though pagination wouldn't trigger new requests to the server even though the url was changing.

This is the final solution that works with pagination using react-router v4.

In <Admin dashboard={Dashboard}> I added:

<Resource name="dashboard-stats"/>

In the Dashboard.js this is what I have:

import React, { Component } from 'react';
import { GET_LIST } from 'react-admin';
import Card from '@material-ui/core/Card';
import CardHeader from '@material-ui/core/CardHeader';

import dataProvider from './dataProvider';
import {
    List,
    TextField,
    Datagrid
} from 'react-admin';


export default class Dashboard extends Component {
    state = {};

    initProps = {
        basePath: "/",
        hasCreate: false,
        hasEdit: false,
        hasList: true,
        hasShow: false,
        location: { pathname: "/", search: "", hash: "", state: undefined },
        match: { path: "/", url: "/", isExact: true, params: {} },
        options: {
        },
        permissions: null,
        resource: "dashboard-stats",
        perPage: 5
    };

    componentWillMount() {
        this.unlisten = this.props.history.listen((location, action) => {

        if (location.search) {
            //regex from: https://stackoverflow.com/a/8649003/1501205
            let queryParams = JSON.parse('{"' + decodeURI(location.search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}')
            let perPage = queryParams.perPage;
            let page = queryParams.page;
            this.initProps.perPage = perPage;
            this.initProps.page = page;
            this.initProps.location = location;
            this.setState({'initProps': this.initProps})

            }

        });
    }
    componentWillUnmount() {
        this.unlisten();
    }


    componentDidMount() {

        this.setState({'initProps': this.initProps});

        dataProvider(GET_LIST, 'stats', {
            sort: { field: 'date', order: 'DESC' },
            pagination: { page: 1, perPage: 50 },
        })
        .then(response => {
            this.setState({'stats':  response.data});
        });
    }

    render() {

        const {
            initProps
        } = this.state;

        if(!initProps) {
            return false;
        }


        return <Card>
            <CardHeader title="Welcome to the Dashboard" />


            <List {...initProps} >
                    <Datagrid>
                        <TextField source="description" />
                        <TextField source="state" />
                        <TextField source="date" />
                    </Datagrid>
                </List>

        </Card>;

    }
}

don't forget to update the location this.initProps.location with the location just changed - otherwise it will work for the first click (route change) and then it will stop working



回答3:

You must be wanting to display data from various resources, otherwise you would just use a regular "List" page.

Dashboard can do this. Have a look at the Demo Dashboard

Multiple dataProvider(GET_LIST,... that you pass on to components. You can use this Demo Dashboard Component as an example. Pending Orders



回答4:

Thanks for the solution. Screen renders with below warning

How to remove all warnings ? Warning: React does not recognize the basePath prop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercase basepath instead. If you accidentally passed it from a parent component, remove it from the DOM element.

Like basePath console shows same warnings with other props "currentSort, defaultTitle, displayedFilters,filterValues,hasCreate,hideFilter,isLoading,loadedOnce,onToggleItem,onUnselectItems,perPage,selectedIds,setFilters,setPage,setPerPage,setSort,showFilter,hasBulkActions"

Warning: Invalid value for prop translate on tag. Either remove it from the element, or pass a string or number value to keep it in the DOM. For details

const initProps = {
  basePath: '/',
  hasCreate: false,
  hasEdit: false,
  hasList: true,
  hasShow: false,
  location: { pathname: '/', search: '', hash: '', state: undefined },
  match: { path: '/', url: '/', isExact: true, params: {} },
  options: {},
  permissions: null,
  resource: 'dashboard',
  perPage: 5
};

<List
{...initProps}
filterDefaultValues={{
  arrivedTimestampStart: moment().format('YYYY-MM-DD'),
  arrivedTimestamp: moment().format('YYYY-MM-DD')
}}
filters={<DashboardFilter />}
sort={{ field: 'arrivedTimestamp', order: 'DESC' }}
pagination={<Fragment />}
exporter={false}
>
<Responsive
  medium={
    <div style={styles.flex}>
     <OtherComponent />
    </div>
    }
/>
</List>


标签: react-admin