How can I manage multiple same component on same page with their respective separate axios request in react?

Viewed 1881

I have React-Redux Application I wanted to make its dashboard on which it will display multiple same components, let me explain how my application broader structure looks like

  1. commonPage root component which holds 2 further components in it

    1. CommonContent (Which displays Table)

    2. CommonContentView (which displays Edit fields for respective table)

Each of these components have request being made in their constructor which brings data back

My Website Each page display only one component at one time either it shows CommonContent OR CommonContentView Component which works perfectly fine.

My Main issue raised when I display same component multiple times on one page here is dashboard components structure which shows multiple CommonContent component on one page

  • Dashboard root component which holds 1 further component in it

    1. DashboardItem (it maps my list of array which holds detail about each table)

      1. DashboardContent (which displays table same like CommonContent component)

Let me share code snippet from Dashboard components

/dashboard.js

class Dashboard extends Component {
constructor(props, context) {
    super(props, context);
    this.url = this.props.match.url;
    this.entity = this.url === '/' ? 'customers' : this.url.split('/')[1];
    this.model = getModel(this.entity);
}
render() {
    const { classes } = this.props;
    return (
        <Wrapper>
            <FilterBar title={this.model.entity.title} entity={this.entity} history={this.props.history} />
            <div className={classes.root}>
                {this.model.entities.map(e => <DashboardItem entity={e.entity} table={e} />)}
            </div>
        </Wrapper>
    )
}

}

./dashboardItem.js

    render() {
    let { classes } = this.props
    return (
        <Wrapper>
            <FilterBar title={this.model.entity.title} entity={this.entity} history={this.props.history} dashboard={true} table={this.props.table} />
            <div className={classes.root}>
                <Card className={classes.card}>
                    <CardContent className={classes.content}>
                        <DashboardContent
                            model={this.model}
                            entity={this.entity}
                            formDialog={ref => (this.formDialog = ref)}
                            show={this.show}
                            handleUpdateFilters={this.handleUpdateFilters}
                            onRef={ref => (this.reload = ref)}
                            table={this.props.table}
                        />
                    </CardContent>
                </Card >
            </div >
        </Wrapper >
    )

}

DashboardContent

/* eslint-disable */
// import CustomerView from "../pages/Material/customerView";

import React from 'react';
import actions from '../../actions/index';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import HTtable from '../../utils/dataTables/HTtable';
import { getQuery } from '../../utils/common/queries';
import FormDialog from '../../components/common/formDialog';
import * as F from '../../utils/common/functions';
import * as service from '../../services/customService';
import toast from '../../utils/common/toastr';
import Spinner from '../../components/common/spinner';
import * as R from 'ramda';

class DashboardContent extends React.Component {
  constructor(props, context) {
    super(props, context);

    this.query = getQuery({ label: this.props.entity });
    this.state = {
      order: 'desc',
      orderBy: 'id',
      currentSelected: -1,
      data: [],
      meta: { count: 0 },
      page: 0,
      prevSkip: 0,
      rowsPerPage: 10,
      rowsPerPageOptions: [1],
      dialog: {
        state: false,
        dialog: {
          title: '',
          desc: ''
        }
      },
      entity: this.props.entity,
      rawKeys: this.props.model.keys,
      actions: this.props.model.actions,
      reloadData: this.props.reloadData,
      currentQuery: this.query,
      spinner: true,
      tableData: this.props.table.data,
      table: this.props.table
    };

    this.query = R.isEmpty(F.getItem(this.props.entity).where)
      ? this.query
      : F.addFilterWhere(this.state, F.getItem(this.props.entity).where);
    this.props.common.getData(this.query);
  }


  componentDidMount = () => {
    this.props.onRef(this);
  };

  componentWillReceiveProps = nextProps => {
    if (nextProps.data !== this.props.data) {
      if (nextProps.data.error) {
        toast.error(nextProps.data.error.message);
        if (nextProps.data.error.code === 401) {
          F.removeSession();
          this.props.history.push('/signin');
        }
        this.setState({ spinner: false });
      } else {
        this.setState({
          currentQuery: this.query,
          data: nextProps.data['records'],
          meta: nextProps.data['meta'],
          spinner: false
        });
      }
    }
  };

  render() {
    return (
      <div>
        <Spinner show={this.state.spinner} />
        <FormDialog
          formDialog={this.props.formDialog}
          handleClick={this.handleClick}
          {...this.state}
          reloadData={this.reloadData}
          state={this.state}
          show={true}
        />
        {/*<CreateForm ref={this.props.create} {...this.state} keys={this.state.create_keys} show={true}/>*/}
        <HTtable
          state={this.state}
          props={this.props}
          isSelected={this.isSelected}
          handleRequestSort={this.handleRequestSort}
          handleClick={this.handleClick}
          displayData={this.displayData}
          handleChangePage={this.handleChangePage}
          handleMetaSkip={this.handleMetaSkip}
          handleChangeRowsPerPage={this.handleChangeRowsPerPage}
          handleDialog={this.handleDialog}
          dashboard={'true'}
        />
      </div>
    );
  }
}

DashboardContent.propTypes = {
  // classes: PropTypes.object.isRequired
};

function mapStateToProps(state, ownProps) {
  return {
    data: state.data
  };
}

function mapDispatchToProps(dispatch) {
  return {
    common: bindActionCreators(actions.dataActions, dispatch)
  };
}

export default withRouter(
  connect(
    mapStateToProps,
    mapDispatchToProps
  )(DashboardContent)
);

Everything above works fine real issue when I display multiple tables on page it uses DashboardContent for each table, which sends request for each seperate query which is handled through redux

if two tables are rendered on page and 2 requests are sent when response is received it is mapped over both tables instead of mapping data to it respective table

I feel this is due to redux because each requests which were made they mapped their response to one data var in state here is reference from DashboardContent.js file

function mapStateToProps(state, ownProps) {
      return {
        data: state.data
      };
    }

    function mapDispatchToProps(dispatch) {
      return {
        common: bindActionCreators(actions.dataActions, dispatch)
      };
    }

here on each request response this mapStateToProps act and map response data to state data shouldn't it update that specific table in which DashboardContent.js request is made

now in short I have multiple DashboardContent.js with their own request data here is example trying to explain multiple table on page how behaves

`DashboardContent.js` -> contains query regarding users
`DashboardContent.js` -> contains query regarding rooms
`DashboardContent.js` -> contains query regarding units 

now when request is completed for any of those requests for instance I say rooms request is resolved and rooms data wull mapped on all above DashboardContent.js tables which should map data only to its respective table same way all queries behave which request resolve at last usually maps on tables here is image which shows infections table query is completed last and it mapped its data over both tablesenter image description here

I hope I was able to convey my Question What will be possible solutions for this do I need to create each redux store for separate table or do I have to create unique table components for each table(which will be less dynamic and against DRY principle) other then this where else I am doing wrong Your help regarding this issue will be help full as it is on going job project, quick help will be great

1 Answers

As far as I can understand you are using same component to call different apis. What I will recommend is make the view part of data which I guess is similar for all 3 types of data as a different component and the container in which api calls are made should be 3 different components with separate api calls and separate redux store so that they don't modify each others data. Because of same redux store the all modify it and all of them receive the same data.

Related