1

I am working on React Table. I am basically a beginner in React. I have a dashboard page where I display a React Table of 8 columns. I have a customize button which will open a popup page, this popup page has 8 check boxes allows me to show/hide those React columns. Initially all the check boxes in this popup page is set to true. When I uncheck a column that particular column get disabled.

There are images in the end to see what I am trying to do.

I will be using this logic for show hide columns (this question was asked by me two days back) - You can see how this is done using a React Table attribute/property called show. When show is true that column/sub column is shown and When show is false that column/sub column is hidden.

The React Table data is like this

const columns = [
 {
    Header: 'Column 1',
    accessor: 'firstName',
    // show: true // shows the particular column (true is default)
   //  show: false // hides the particular column
  },
  {
    Header: 'Column 2',
    accessor: 'firstName',
  },
  {
    Header: 'Column 3',
    accessor: 'firstName',
  },
  {
    Header: 'Column 4',
    accessor: 'firstName',
  },
  {
    Header: 'Column 5',
    accessor: 'firstName',
  },
  {
    Header: 'Column 6',
    accessor: 'firstName',
  },
  {
    Header: 'Column 7',
    accessor: 'firstName'
  },
  {
    Header: 'Column 8',
    accessor: 'firstName',
  }
];

Now have a look at this image. The image shows my dashboard page along with the checkbox popup page which can turn my column on/off (or show/hide)

Image of dashboard and checkbox page

This is the code for the popup page for checkbox

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { ActionCreators } from '../../../actions';
import ButtonComponent from '../../common/button/ButtonComponent';
import { CheckBox } from '../../common/chkbox/CheckBox';

class CustomizedView extends Component {
  constructor(props) {
    super(props);
    this.handleCheckChildElement = this.handleCheckChildElement.bind(this);
    this.state = {
      items: [
        { id: 1, value: 'Column 1', isChecked: true },
        { id: 2, value: 'Column 2', isChecked: true },
        { id: 3, value: 'Column 3', isChecked: true },
        { id: 4, value: 'Column 4', isChecked: true },
        { id: 5, value: 'Column 5', isChecked: true },
        { id: 6, value: 'Column 6', isChecked: true },
        { id: 7, value: 'Column 7', isChecked: true },
        { id: 8, value: 'Column 8', isChecked: true },
      ]
    };
  }

  handleClick() {
    this.setState({ isChecked: !this.state.isChecked });
  }

  handleCheckChildElement(event) {
    const { items } = this.state; //extract state values like this to a const variable
    const newItems = items.map((item) => { //do map on items because map returns a new array. It’s good practice to use .map than forEach in your case
      if(item.value === event.target.value) {
        item.isChecked = event.target.checked;
        return item; //return updated item object so that it will be pushed to the newItems array
      }
      return item; // return item because you need this item object as well
    });
    this.setState({ items: newItems }); //finally set newItems array into items
    const column1checked = items[0].isChecked;
    console.log('column1checked ' + column1checked);
    const column2checked = items[1].isChecked;
    console.log('column2checked ' + column2checked);
    const column3checked = items[2].isChecked;
    console.log('column3checked ' + column3checked);
    const column4checked = items[3].isChecked;
    console.log('column4checked ' + column4checked);
    const column5checked = items[4].isChecked;
    console.log('column5checked ' + column5checked);
    const column6checked = items[5].isChecked;
    console.log('column6checked ' + column6checked);
    const column7checked = items[6].isChecked;
    console.log('column7checked ' + column7checked);
    const column8checked = items[7].isChecked;
    console.log('column8checked ' + column8checked);
  }

  render() {
    return (
      <div className='div-container-custom' >
        <div className='bottomBar'>
          <ButtonComponent
            text='Apply'
            className='activeButton filterMargin-custom'
            width='100'
            display='inline-block'
            onClick={() => { this.props.applyFilter(this.state, false); }}
          />
          <ButtonComponent
            text='Clear Filter'
            className='greyedButton clear-custom-filter'
            width='100'
            display='block'
            marginTop='60'
            onClick={() => { this.props.applyFilter(this.state, true); }}
          />
        </div>
        <div>
          <div className='data-points-text'>
            <span> Columns </span>
          </div>
          <div className="App">
            <ul>
              {
                this.state.items.map((item, i) => {
                  return (<div key={i} ><CheckBox handleCheckChildElement={this.handleCheckChildElement} {...item} /></div>);
                })
              };
            </ul>
          </div>
        </div>
      </div>
    );
  }
}

CustomizedView.propTypes = {
  applyFilter: PropTypes.func.isRequired
};

CustomizedView.defaultProps = {
};

function mapStateToProps(state) {
  return {
    auth: state.auth
  };
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(ActionCreators, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(CustomizedView);

Now my point is when I only uncheck 4th column in the checkbox popup page I get the desired values (the above code)

column1checked true
column2checked true
column3checked true
column4checked false
column5checked true
column6checked true
column7checked true
column8checked true

And ultimately this is my checkbox page

import React from 'react';
import PropTypes from 'prop-types';

export const CheckBox = (props) => {
  // super(props);
  return (
    <li>
      <input key={props.id} onClick={props.handleCheckChildElement} type="checkbox" checked={props.isChecked} value={props.value} /> {props.value}
    </li>
  );
};

CheckBox.propTypes = {
  id: PropTypes.string,
  handleCheckChildElement: PropTypes.func,
  isChecked: PropTypes.bool,
  value: PropTypes.string,
};

export default CheckBox;

Now my question is I have the constants in CustomizedView Component. I need those const variables available in ReactTable Component (path is like this - '../../common/chkbox/CheckBox')

In the main dashboard page I import the React Table

import ReactTableComponent from '../common/react_table/ReactTableComponent';

and just use it in the render function of the main dashboard page in this way.

<ReactTableComponent />

So I need to use all those const variables of Customized variables in ReactTable Component to show/hide tables.

Also here I have to use show: some_const (I cannot use true or false)

I am a complete beginner in React and I need help from this community. Kindly help to implement this idea.

All I want to know the best/easiest (may be great way or dumb way) way to transfer those 8 const variables from components\abcdashboard\customized_view\Customizedview to components\common\react_table\ReactTableComponent

1 Answers1

2

Generally, when you want to share data across components like this, what you want is to consolidate the data in a higher-up component, and use functions to modify it.

Here's a contrived example (CodeSandbox here):

import React from "react";
import ReactDOM from "react-dom";

class Parent extends React.Component {
  state = {
    name: "Bill"
  };

  changeName = name => {
    this.setState({ name });
  };

  render() {
    return (
      <React.Fragment>
        <h1>name is: {this.state.name}</h1>
        <ChildA changeName={this.changeName} />
        <ChildB changeName={this.changeName} />
      </React.Fragment>
    );
  }
}

class ChildA extends React.Component {
  state = {
    nameA: "Steve"
  };

  render() {
    return (
      <button onClick={() => this.props.changeName(this.state.nameA)}>
        change to my name
      </button>
    );
  }
}

class ChildB extends React.Component {
  state = {
    nameB: "Elon"
  };

  render() {
    return (
      <button onClick={() => this.props.changeName(this.state.nameB)}>
        change to my name
      </button>
    );
  }
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Parent />, rootElement);

Here, the Parent can access the value of the names of the children through the changeName function which is passed down.

If you just want to share variables and not data per se, you could just define a whole file and export various variables like:

export const PI = 3.14

and so on, then do like:

import { PI } from './variables'

in other files, for example.

Colin Ricardo
  • 16,488
  • 11
  • 47
  • 80
  • Any other solution apart from React Fragments ? –  Dec 09 '18 at 18:04
  • 1
    You can basically view React Fragments as divs, so they don't change anything in my answer here. – Colin Ricardo Dec 09 '18 at 18:05
  • I am a complete beginner in React. Can you suggest the best way to transfer those 8 const variables from components\abcdashboard\customized_view\Customizedview to components\common\react_table\ReactTableComponent –  Dec 09 '18 at 18:10
  • Since they're part of state, then the easiest way to do it is to pass a function from `ReactTableComponent` to `CustomizedView`. – Colin Ricardo Dec 09 '18 at 18:11
  • Please show me how as I am completely new to React. –  Dec 09 '18 at 18:12
  • are you there? Please reply to me –  Dec 09 '18 at 18:22