Oleksandr Tatarinov
Oleksandr Tatarinov

Reputation: 323

How can i push data into react-admin store?

I'm trying to build a web app with react-admin and need to push data to the redux store. I read the React-admin docs (https://marmelab.com/react-admin/Actions.html) and when I try to do that, I get Failures.enter image description here

Here is my code

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { withStyles, MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import {
    Menu,
    Notification,
    Sidebar,
        setSidebarVisibility, 
} from 'react-admin';

import {kidsLoad} from './customActions/KidsActions'

import AppBar from './MyAppBar';
const styles = theme => ({
    root: {
        display: 'flex',
        flexDirection: 'column',
        zIndex: 1,
        minHeight: '100vh',
        backgroundColor: theme.palette.background.default,
        position: 'relative',
    },
    appFrame: {
        display: 'flex',
        flexDirection: 'column',
        overflowX: 'auto',
    },
    contentWithSidebar: {
        display: 'flex',
        flexGrow: 1,
    },
    content: {
        display: 'flex',
        flexDirection: 'column',
        flexGrow: 2,
        padding: theme.spacing.unit * 3,
        marginTop: '1em',
        paddingLeft: 5,
    },
});

class MyLayout extends Component {
    componentWillMount() {
        this.props.setSidebarVisibility(true);
        }

        componentDidMount(){
            const { kidsLoad, record } = this.props;

            kidsLoad({data: "HELLOOOOOOOOOOOO!!!!!"})

        }

    render() {
        const {
            children,
            classes,
            dashboard,
            isLoading,
            logout,
            open,
            title,
        } = this.props;
        return (
            <div className={classes.root}>
                <div className={classes.appFrame}>
                    <AppBar title={title} open={open} logout={logout} />
                    <main className={classes.contentWithSidebar}>

                        <div className={classes.content}>
                            {children}
                        </div>
                    </main>
                    <Notification />
                </div>
            </div>
        );
    }
}

MyLayout.propTypes = {
    children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]),
    dashboard: PropTypes.oneOfType([
        PropTypes.func,
        PropTypes.string,
    ]),
    isLoading: PropTypes.bool.isRequired,
    // logout: componentPropType,
    setSidebarVisibility: PropTypes.func.isRequired,
        title: PropTypes.string.isRequired,
        kidsLoad: PropTypes.func,
};

const mapStateToProps = state => ({ isLoading: state.admin.loading > 0 });
export default connect(mapStateToProps, { setSidebarVisibility, kidsLoad })(withStyles(styles)(MyLayout));

I did everything like in the documentation (https://marmelab.com/react-admin/Actions.html).

What did I do wrong? How do you add data to the store in this framework?

Upvotes: 3

Views: 4055

Answers (1)

Ed Gomoliako
Ed Gomoliako

Reputation: 1040

This is going to be a quick answer that I leave for further improvement.

If I understand your question correctly you got some of your resources (entities) updated and you want react-admin to know about it and update its store accordingly triggering updates in app views if necessary.

The first thing we have to get is the dispatch function of the react-admin store. In my case, the source of resource update was a React component, so I used withDataProvider decorator to receive a reference to the dispatch function.

Once you have the dispatch function you dispatch, for example, CRUD_UPDATE_SUCCESS action for a particular resource update in the react-admin store.

import { CRUD_UPDATE_SUCCESS, FETCH_END, UPDATE } from 'react-admin';

dispatch({
  type: CRUD_UPDATE_SUCCESS,
  payload: { data },
  meta: {
    resource,
    notification: {
      body: 'ra.notification.dataSaved',
      level: 'info'
    },
    fetchResponse: UPDATE,
    fetchStatus: FETCH_END
  }
});

You can also use action creators from react-admin. Like showNotification, for example.

import { showNotification } from 'react-admin';

dispatch(showNotification(errorMessage, 'warning', { autoHideDuration: 10000 }));

A bit more consistent piece of code here to show how all this can work together. The Updater component here renders its child components passing them a resource record and subscribes for their onSubmit callback to perform entity saving and updating react-admin store.

import React from 'react';
import { 
  CRUD_UPDATE_SUCCESS, FETCH_END, UPDATE, withDataProvider, showNotification 
} from 'react-admin';

class Updater extends React.Component {
  constructor(props) {
    super(props);

    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleUpdate(record) {
    const { resource, dataProvider, dispatch } = this.props;

    const payload = {
      id: record.id,
    };

    payload.data = {...record};

    return new Promise((resolve, reject) => {
      dataProvider(UPDATE, resource, payload)
        .then(({data}) => {
          dispatch({
            type: CRUD_UPDATE_SUCCESS,
            payload: { data },
            meta: {
              resource,
              notification: {
                body: 'ra.notification.dataSaved',
                level: 'info'
              },
              fetchResponse: UPDATE,
              fetchStatus: FETCH_END
            }
          });

          resolve(data);
        })
        .catch(e => {
          const errorMessage = e.message || e;

          this.setState({ errorMessage });

          dispatch(
            showNotification(errorMessage, 'warning', { autoHideDuration: 10000 })
          );

          reject(errorMessage);
        });
    });
  }

  render() {
    const { record, children } = this.props;
    const { errorMessage } = this.state;

    return React.Children.only(React.cloneElement(children, {
      record,
      errorMessage,
      onUpdate: this.handleUpdate
    }));
  }
}

export default withDataProvider(Updater);

HTH, Ed

Upvotes: 4

Related Questions