skip to Main Content

I have a react app with several components. I have a dashboard component with a sidebar that has a tab to upload a file and the responsible component is ‘addData’. After uploading the file and sending it to the server, in the callback I am redirecting to a different component called ‘visualize’.

Shown below is my AddData.jsx

import {withStyles} from '@material-ui/core'
import PropTypes    from 'prop-types'
import * as React   from 'react'
import styles       from './AddData.styles'
import { withRouter } from 'react-router-dom';

class AddData extends React.Component {

  constructor(props) {
    super(props);

    this.state = {
      fileType : "null",
      fileData : "null"
    };

  }

  validateFileType(e)
  {
    var name = null
    let filepath= e.target.value;
    var ext = filepath.substring(filepath.lastIndexOf('.') + 1);
    this.setState({fileData:e.target.files[0]}) 
    if(this.state.fileType == "null"){
      e.target.value = ""
      alert("Select File Type");
    }
    else{
      if(ext != this.state.fileType ) {
        e.target.value = ""
        alert("Unsupported File Type");
      }    
    }
  }

  updateFileType(e)
  {
    this.setState({fileType: e.target.value});    
  }

  handleSubmit(e)
  {
    e.preventDefault();

    if(this.state.fileType == "null" || this.state.fileData == "null"){
      alert("Select File Type And Upload File")
    }
    else{

      const data = new FormData();
      data.append('file', this.state.fileData);

      fetch('http://127.0.0.1:5000/addData', {
        method: 'POST',
        body: data,
      }).then((response) => {
        return response.text();
      }).then((responseText) => {
        console.log(responseText);
        if(responseText == "error"){
          alert ("Dataset with identical name already exists");
        }
        else{
          let path = "/visualize";
          this.props.history.push(path);
        }       
     }).catch(function (error) {
      console.log(error);
    });

  }

  }

  render() {

    const {classes} = this.props

    return (
        <div className={classes.container}>
        <form onSubmit={this.handleSubmit.bind(this)}>
            <label>File Type:</label>  
          <select name="data_format" className={classes.text} onChange={this.updateFileType.bind(this)}>
            <option value="null">Select Type of File</option>
            <option value="csv">csv</option>
          </select><br/>
          <label>Select file: </label>          
          <input type="file" name="dataset_csv" className={classes.browse} accept=".csv" onChange={this.validateFileType.bind(this)}></input><br/>
            <input type="submit" value="Upload" className={classes.submit}></input>
        </form>
        </div>
    )
  }

}

AddData.propTypes = {
  classes: PropTypes.object.isRequired,
  theme  : PropTypes.object.isRequired,
}

export default withStyles(styles, {withTheme: true})(AddData)

In the visualize component I need to access fileType information in this.state in the addData component. I am new to react how can this be done?

shown below is my VisualizeData.jsx

import {withStyles} from '@material-ui/core'
import PropTypes    from 'prop-types'
import * as React   from 'react'
import styles       from './VisualizeData.styles'

class VisualizeData extends React.Component {
  constructor() {
    super();
    this.addNewRow = this.addNewRow.bind(this);
    this.addNewCol = this.addNewCol.bind(this);
    this.delRow = this.delRow.bind(this);
    this.delCol = this.delCol.bind(this);
    this.highlightRow = this.highlightRow.bind(this);
    this.highlightCol = this.highlightCol.bind(this);
    this.makeEditable = this.makeEditable.bind(this);
    this.handleInputChange = this.handleInputChange.bind(this);
    this.savVal = this.savVal.bind(this);
    this.canVal = this.canVal.bind(this);
    //var Httpreq = new XMLHttpRequest();
    //Httpreq.open("GET", '/visualizeData?' + 'name=IMAGENET', false);
    //Httpreq.send(null);
    //var response = Httpreq.responseText.split("n");
//     var response = `Model,mpg,cyl,disp,hp,drat,wt,qsec,vs,am,gear,carb
// Mazda RX4,21,6,160,110,3.9,2.62,16.46,0,1,4,4
// Mazda RX4 Wag,21,6,160,110,3.9,2.875,17.02,0,1,4,4
// Datsun 710,22.8,4,108,93,3.85,2.32,18.61,1,1,4,1
// Hornet 4 Drive,21.4,6,258,110,3.08,3.215,19.44,1,0,3,1
// Hornet Sportabout,18.7,8,360,175,3.15,3.44,17.02,0,0,3,2
// Valiant,18.1,6,225,105,2.76,3.46,20.22,1,0,3,1
// Duster 360,14.3,8,360,245,3.21,3.57,15.84,0,0,3,4
// Merc 240D,24.4,4,146.7,62,3.69,3.19,20,1,0,4,2
// Merc 230,22.8,4,140.8,95,3.92,3.15,22.9,1,0,4,2
// Merc 280,19.2,6,167.6,123,3.92,3.44,18.3,1,0,4,4
// Merc 280C,17.8,6,167.6,123,3.92,3.44,18.9,1,0,4,4
// Merc 450SE,16.4,8,275.8,180,3.07,4.07,17.4,0,0,3,3
// Merc 450SL,17.3,8,275.8,180,3.07,3.73,17.6,0,0,3,3
// Merc 450SLC,15.2,8,275.8,180,3.07,3.78,18,0,0,3,3
// Cadillac Fleetwood,10.4,8,472,205,2.93,5.25,17.98,0,0,3,4
// Lincoln Continental,10.4,8,460,215,3,5.424,17.82,0,0,3,4
// Chrysler Imperial,14.7,8,440,230,3.23,5.345,17.42,0,0,3,4
// Fiat 128,32.4,4,78.7,66,4.08,2.2,19.47,1,1,4,1`.split("n");
    this.state = {
      sampleData: "null"
    };
  }

  componentDidMount() {
    fetch('http://127.0.0.1:5000/visualizeData', {
      method: 'GET'
    }).then((response) => {
      return response.text();
    }).then((responseText) => {
      console.log(responseText.split("n"))  
      this.setState({sampleData: responseText.split("n")})    
   }).catch(function (error) {
      console.log(error);
  });


  }

  addNewRow() {
    const {sampleData} = this.state;
    var rows = sampleData.length;
    var cols = sampleData[0].split(",").length;
    var str = "";
    var array = null;
    if(this.state.selectRow != null) {
      var array = sampleData[this.state.selectRow].split(",");
    }
    for(var i=0;i<cols;i++) {
      if(i == 0) {
        str += "Row" + rows.toString();
      }
      else if(array != null) {
        str += "," + array[i];
      }
      else {
        str += ",0";
      }
    }
    sampleData.push(str);
    this.setState({
      sampleData: sampleData
    });
  }

  addNewCol() {
    const {sampleData} = this.state;
    var cols = sampleData[0].split(",").length;
    var array = [];
    if(this.state.selectCol != null) {
      for(var i = 0;i<sampleData.length;i++) {
        array.push(sampleData[i].split(",")[this.state.selectCol]);
      }
    }
    for(var i=0;i<sampleData.length;i++) {
      if(i == 0) {
        sampleData[i] += ",Col" + cols.toString();
      }
      else if(array != null && array.length > 0) {
        sampleData[i] += "," + array[i];
      }
      else {
        sampleData[i] += ",0";
      }
    }
    this.setState({
      sampleData: sampleData
    });
  }

  highlightRow(event) {
    if(this.state.selectRow != Number(event.target.id)) {
      this.setState({
        selectRow: Number(event.target.id)
      })
    }
    else {
      this.setState({
        selectRow: null
      })
    }
  }

  highlightCol(event) {
    if(this.state.selectCol != Number(event.target.id)) {
      this.setState({
        selectCol: Number(event.target.id)
      })
    }
    else {
      this.setState({
        selectCol: null
      })
    } 
  }

  renderCols(data, row) {
    const {classes} = this.props
    return data.map((ele, idx) => {
      if(idx == 0) {
        if(this.state.selectCol != null && this.state.selectCol == idx) {
          return <td className={classes.tabletd} id={row} onClick={this.highlightRow} className={classes.highlightCol}>{ele}</td>
        }
        else {
          return <td className={classes.tabletd} id={row} onClick={this.highlightRow}>{ele}</td>
        }
      }
      else if(row == 0 && idx != 0) {
        if(this.state.selectCol != null && this.state.selecCol == idx) {
          return <td className={classes.tabletd} id={idx} onClick={this.highlightCol} className={classes.highlightCol}>{ele}</td>
        }
        else {
          return <td className={classes.tabletd} id={idx} onClick={this.highlightCol}>{ele}</td>
        }
      }
      else {
        if(this.state.selectCol != null && this.state.selectCol == idx) {
          if(this.state.editRow != null && this.state.editCol != null && this.state.editRow == row && this.state.editCol == idx) {
            return <td className={classes.tabletd} id={row + ',' + idx} onDoubleClick={this.makeEditable} className={classes.highlightCol}><input className={classes.inputdata} type="text" defaultValue={ele}/></td>
          }
          else {
            return <td className={classes.tabletd} id={row + ',' + idx} onDoubleClick={this.makeEditable} className={classes.highlightCol} className={classes.input}>{ele}</td>
          }
        }
        else {  
          if(this.state.editRow != null && this.state.editCol != null && this.state.editRow == row && this.state.editCol == idx) {    
            return <td className={classes.tabletd} id={row + ',' + idx} onDoubleClick={this.makeEditable}><input className={classes.inputdata} type="text" defaultValue={ele} onChange={this.handleInputChange}/></td>
          }
          else {
            return <td className={classes.tabletd} id={row + ',' + idx} onDoubleClick={this.makeEditable}>{ele}</td>
          }
        }
      }
    }, this);
  }

  handleInputChange(event) {
    this.newValue = event.target.value;
  }
  makeEditable(event) {
    var id = event.target.id;
    var row = Number(id.split(",")[0]);
    var col = Number(id.split(",")[1]);
    console.log(row, col);
    this.setState({
      editRow: row,
      editCol: col
    })
  }

  renderRows(data) {
    const {classes} = this.props
    return data.map((ele, idx) => {
      if(this.state.selectRow != null && this.state.selectRow == idx) {
        return <tr className={classes.highlightRow} >{this.renderCols(ele.split(","), idx)}</tr>;
      }
      else {
        return <tr>{this.renderCols(ele.split(","), idx)}</tr>;
      }
    });
  }

  delRow() {
    if(this.state.selectRow != null) {
      var {sampleData} = this.state;
      sampleData.splice(this.state.selectRow, 1);
      this.setState({
        sampleData: sampleData,
        selectRow: null
      })
    }
  }

  delCol() {
    if(this.state.selectCol != null) {
      var {sampleData} = this.state;
      for(var i=0;i<sampleData.length;i++) {
        sampleData[i] = sampleData[i].split(",");
        sampleData[i].splice(this.state.selectCol, 1);
        sampleData[i] = sampleData[i].join(",");
      }
      this.setState({
        sampleData: sampleData,
        selectCol: null
      })
    }
  }
  renderDelRow() {
  const {classes} = this.props;
    return <button className={classes.viewbtn} onClick={this.delRow}>Delete row</button>
  }

  renderDelCol() {
  const {classes} = this.props;
    return <button className={classes.viewbtn} onClick={this.delCol}>Delete col</button>
  }

  renderAddRow() {
  const {classes} = this.props;
    return <button className={classes.viewbtn} onClick={this.addNewRow}>Add row</button>
  }

  renderAddCol() {
  const {classes} = this.props;
    return <button className={classes.viewbtn} onClick={this.addNewCol}>Add col</button>
  }

  renderDelBtn() {
  const {classes} = this.props;
    return <button className={classes.viewbtn} onClick={this.delRow}>Del row</button>
  }

  renderSavVal() {
  const {classes} = this.props;
    return <button className={classes.viewbtn} onClick={this.savVal}>Save value</button>
  }

  renderCanVal() {
  const {classes} = this.props;
    return <button className={classes.viewbtn} onClick={this.canVal}>Cancel</button>
  }

  savVal() {
    if(this.state.editCol != null && this.state.editRow != null) {
      const {sampleData} = this.state;
      var editRow = this.state.editRow;
      var editCol = this.state.editCol;
      sampleData[editRow] = sampleData[editRow].split(",")
      sampleData[editRow][editCol] = this.newValue;
      sampleData[editRow] = sampleData[editRow].join(",");
      this.setState({
        sampleData: sampleData,
        editRow: null,
        editCol: null
      })
    }
  }

  canVal() {
    this.setState({
      editRow: null,
      editCol: null
    })
  }

  render() {
    const {sampleData} = this.state;
    const {classes} = this.props;
    const {match} = this.props;

    return (
      <div className={classes.container}>
        <table className={classes.table}>
          <tr>
            <td className={classes.tabletd}>Welcome to {match.params.name}</td>
            <td className={classes.tabletd}>Operations</td>
          </tr>
          <tr>
            <td className={classes.tabletd}>
              <table className={classes.table}>
                {this.renderRows(sampleData)}
              </table>
            </td>
            <td className={classes.tabletd}>
              {this.renderAddRow()}<br/>
              {this.renderAddCol()}<br/>
              {this.renderDelRow()}<br/>
              {this.renderDelCol()}<br/>
              {this.renderSavVal()}<br/>
              {this.renderCanVal()}<br/>
              <button className={classes.viewbtn}>Pass to network</button>
            </td>
          </tr>
        </table>
      </div>
    )
  }
}

VisualizeData.propTypes = {
  classes: PropTypes.object.isRequired,
  theme  : PropTypes.object.isRequired,
}

export default withStyles(styles, {withTheme: true})(VisualizeData)

shown below is the App.js

import {withStyles}    from '@material-ui/core/styles'
import PropTypes       from 'prop-types'
import React           from 'react'
import {Route, Router} from 'react-router-dom'
import styles          from './App.styles'
import {history}       from './helpers'
import {Dashboard}     from './pages/dashboard'
// import {AddData}       from './pages/adddata'
// import {ViewData}      from './pages/viewdata'
import {VisualizeData} from './pages/visualizedata'

class App extends React.Component {

  render() {
    const {classes} = this.props

    return (
        <div className={classes.root}>
          <Router history={history}>
            <div>

              <Route path="/visualize" component={VisualizeData}/>
              {/* <Route path="/viewdata" component={ViewData}/> */}
              <Route path="/" component={Dashboard}/>
              {/*<PrivateRoute exact path="/" component={Dashboard}/>*/}
              {/*<Route path="/login" component={SignIn}/>*/}
              {/*<Route path="/register" component={SignUp}/>*/}
            </div>
          </Router>
        </div>
    )
  }

}

App.propTypes = {
  classes: PropTypes.object.isRequired,
}

export default withStyles(styles, {withTheme: true})(App)

Shown below is my Dashboard.jsx

import {withStyles} from '@material-ui/core'
import CssBaseline  from '@material-ui/core/CssBaseline'
import PropTypes    from 'prop-types'
import * as React   from 'react'
import {Route}      from 'react-router-dom'
import {Home}       from './scenes/home'
import {A}        from './scenes/a'
import {B}        from './scenes/b'
import {AddData}   from '../adddata'
import {Header}     from './components/header'
import {Sidebar}    from './components/sidebar'
import styles       from './Dashboard.styles'

class Dashboard extends React.Component {

  render() {
    const {classes} = this.props
    console.log(window.location.href);
    var url_ = new URL(window.location.href);
    console.log(url_);
    return (

        <div className={classes.root}>
          <CssBaseline/>
          {url_.pathname !== '/neuralnet' &&
              <Header/>
          }
          <Sidebar/>
          <main className={classes.content}>
            {url_.pathname !== '/neuralnet' &&
                <div className={classes.toolbar}/>
            }
            <Route path="/adddata" component={AddData}/>
            <Route exact path='/home' component={Home}/>
            <Route exact path='/neuralnet' component={A}/>
            <Route exact path='/b' component={B}/>
            <Route exact path='/' component={B}/>
          </main>
        </div>
    )
  }

}

Dashboard.propTypes = {
  classes: PropTypes.object.isRequired,
  theme  : PropTypes.object.isRequired,
}

export default withStyles(styles, {withTheme: true})(Dashboard)

shown below is my sidebar.jsx

import {withStyles}     from '@material-ui/core'
import Divider          from '@material-ui/core/Divider/index'
import Drawer           from '@material-ui/core/Drawer/index'
import Hidden           from '@material-ui/core/Hidden/index'
import List             from '@material-ui/core/List/index'
import ListItem         from '@material-ui/core/ListItem/index'
import ListItemIcon     from '@material-ui/core/ListItemIcon/index'
import ListItemText     from '@material-ui/core/ListItemText/index'
import ListSubheader    from '@material-ui/core/ListSubheader/index'
import FindInPageIcon   from '@material-ui/icons/FindInPage'
import HomeIcon         from '@material-ui/icons/Home'
import LibraryBooksIcon from '@material-ui/icons/LibraryBooks'
import PropTypes        from 'prop-types'
import * as React       from 'react'
import {Link}           from 'react-router-dom'
import styles           from './Sidebar.styles'


class Sidebar extends React.Component {

  state = {
    mobileOpen: false,
  }

  handleDrawerToggle = () => {
    this.setState(state => ({mobileOpen: !state.mobileOpen}))
  }

  render() {
    const {classes, theme} = this.props


    const drawer = (
        <div>
          <List
              component="nav"
              subheader={<ListSubheader component="div">TensorMap</ListSubheader>}
          >
            <ListItem button component={Link} to="/home">
              <ListItemIcon>
                <HomeIcon/>
              </ListItemIcon>
              <ListItemText inset primary="Home"/>
            </ListItem>
            <Divider/>
            <ListItem button component={Link} to="/adddata">
              <ListItemIcon>
                <LibraryBooksIcon/>
              </ListItemIcon>
              <ListItemText inset primary="Pre-processing"/>
            </ListItem>
            <ListItem button component={Link} to="/neuralnet">
              <ListItemIcon>
                <LibraryBooksIcon/>
              </ListItemIcon>
              <ListItemText inset primary="Neural Networks"/>
            </ListItem>
            <ListItem button component={Link} to="/b">
              <ListItemIcon>
                <FindInPageIcon/>
              </ListItemIcon>
              <ListItemText inset primary="B"/>
            </ListItem>
            <Divider/>
          </List>
        </div>
    )

    return (
        <nav className={classes.drawer}>
          {/* The implementation can be swapped with js to avoid SEO duplication of links. */}
          <Hidden smUp implementation="css">
            <Drawer
                // container={this.props.container}
                variant="temporary"
                anchor={theme.direction === 'rtl' ? 'right' : 'left'}
                open={this.state.mobileOpen}
                onClose={this.handleDrawerToggle}
                classes={{
                  paper: classes.drawerPaper,
                }}
            >
              {drawer}
            </Drawer>
          </Hidden>
          <Hidden xsDown implementation="css">
            <Drawer
                classes={{
                  paper: classes.drawerPaper,
                }}
                variant="permanent"
                open
            >
              {drawer}
            </Drawer>
          </Hidden>
        </nav>
    )
  }

}

Sidebar.propTypes = {
  classes: PropTypes.object.isRequired,
  theme  : PropTypes.object.isRequired,
}

export default withStyles(styles, {withTheme: true})(Sidebar)

3

Answers


  1. Chosen as BEST ANSWER

    I solved this by using:

    this.props.history.push(
                '/visualize',
                {
                  fileName: responseText,
                }
              )
    

    In AddData.jsx to navigate to the VisualizeData component. And Inside the VisualizeData.jsx I put the below code to access the information.

    componentDidMount() { 
        this.setState({fileType: this.props.location.state.fileType})
    }
    

  2. The most simple way to pass data from one component to another is through prop drilling–passing the data from the parent to its children until it reaches the child component where it’s needed. You pass the data as a property to the component thats being rendered. Example:

    class Parent extends React.Component{
    constructor(prop){
    super(prop);
    this.state ={
    someData:true,
    }
    }
    render(){
    return(
    <ChildComponent passData ={this.state.someData}/>
    )
    }
    }
    

    The state is going to be accessed in the child component from the props property. this.props.passData will hold the state in the Child Component.

    Login or Signup to reply.
  3. I would recommend using a url query it’s very easy to add that to your existing code, here’s an example:

    let path = `/visualize?fileType={this.state.fileType}`;
    this.props.history.push(path);
    

    In your VisualizeData.jsx you could run some function to extract the query values, I like to use query-string parse function:

    EDIT: Forgot to mention that you can read your query with window.location or if you are using react router (withRouter) you can take it from location prop

    import * as qs from 'query-string';
    ...
    constructor(props) {
      super(props);
      // You can add this to componentDidMount, componentDidUpdate or render method
    
      const { location } = this.props; // Comes with router
      const { search } = location;
      const query = qs.parse(search, { ignoreQueryPrefix: true });
      this.state = {
       fileType: query.fileType || ''
      };
    }
    

    Hope it helps

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search