Search code examples
javascriptreactjsjavascript-objects

How can I access props from inside a component


I'm trying to access "props" from a component for which I'm passing an object. I'm a bit lost with JS here ; basically what I'm trying to do is to build a Master/Detail view (so show/hide 2 different components based on user clicks on a table).

How can I access "props" from the object rowEvent once a user clicks on a table row ?

const rowEvents = {
    onClick: (e, row, rowIndex) => {
      console.log(row.itemId);
      //this.currentItemId= row.itemId;   //////////// THIS DOESNT WORK...
    }
};


const TableWithSearch = (props) => {
    const { SearchBar } = Search;
    const { ExportCSVButton } = CSVExport;

return (
    <Card>
        <CardBody>
            <h4 className="header-title">Search and Export</h4>
            <p className="text-muted font-14 mb-4">A Table</p>

            <ToolkitProvider
                bootstrap4
                keyField="itemId"
                data={props.data}
                columns={columns}
                search
                exportCSV={{ onlyExportFiltered: true, exportAll: false }}>
                {props => (
                    <React.Fragment>
                        <Row>
                            <Col>
                                <SearchBar {...props.searchProps} />
                            </Col>
                            <Col className="text-right">
                                <ExportCSVButton {...props.csvProps} className="btn btn-primary">
                                    Export CSV
                                </ExportCSVButton>
                            </Col>
                        </Row>

                        <BootstrapTable
                            {...props.baseProps}
                            bordered={false}
                            rowEvents={ rowEvents }
                            defaultSorted={defaultSorted}
                            pagination={paginationFactory({ sizePerPage: 5 })}
                            wrapperClasses="table-responsive"
                        />
                    </React.Fragment>
                )}
            </ToolkitProvider>
        </CardBody>
    </Card>
);
};

And the component looks like this :

render() {

    let show;

    if (this.props.currentItemId === null){
        show = (<TableWithSearch data={this.props.data} />)
    }
    else {
        show = (<DisplayItem />)
    }

    return (
        <React.Fragment>
            <Row>
                <Col>
                    { show }
                </Col>
            </Row>
        </React.Fragment>
    )
}
}

Solution

  • Your issue is a bit complex because you seem to be needing to update the prop currentItemId from parent's parent.

    You can solve your issue by doing the following:

    • Move the declaration of rowEvents objects in side TableWithSearch functional component.
    • In TableWithSearch component, receive a callback say updateCurrentItemId from parent which updates the currentItemId in the parent
    • In parent component, the currentItemId is being passed from parent(again). So maintain a state for it.

    TableWithSearch Component

    const TableWithSearch = (props) => {
      const { SearchBar } = Search;
      const { ExportCSVButton } = CSVExport;
      const {updateCurrentItemId} = props; //<--------- receive the prop callback from parent
      const rowEvents = {
        onClick: (e, row, rowIndex) => {
          console.log(row.itemId);
          updateCurrentItemId(row.itemId) // <--------- use a callback which updates the currentItemId in the parent
          //this.currentItemId= row.itemId;   //////////// THIS DOESNT WORK...
        },
      };
      return (
        <Card>
          <CardBody>
            <h4 className="header-title">Search and Export</h4>
            <p className="text-muted font-14 mb-4">A Table</p>
    
            <ToolkitProvider
              bootstrap4
              keyField="itemId"
              data={props.data}
              columns={columns}
              search
              exportCSV={{ onlyExportFiltered: true, exportAll: false }}
            >
              {(props) => (
                <React.Fragment>
                  <Row>
                    <Col>
                      <SearchBar {...props.searchProps} />
                    </Col>
                    <Col className="text-right">
                      <ExportCSVButton
                        {...props.csvProps}
                        className="btn btn-primary"
                      >
                        Export CSV
                      </ExportCSVButton>
                    </Col>
                  </Row>
    
                  <BootstrapTable
                    {...props.baseProps}
                    bordered={false}
                    rowEvents={rowEvents}
                    defaultSorted={defaultSorted}
                    pagination={paginationFactory({ sizePerPage: 5 })}
                    wrapperClasses="table-responsive"
                  />
                </React.Fragment>
              )}
            </ToolkitProvider>
          </CardBody>
        </Card>
      );
    };
    

    Parent Component

    class ParentComp extends React.Component {
        state = {
            curItemId: this.props.currentItemId
        }
        updateCurrentItemId = (udpatedCurId) => {
            this.setState({
                curItemId: udpatedCurId
            })
        }
        render() {
    
            let show;
    
            // if (this.props.currentItemId === null){
            if (this.state.curItemId === null){
                show = (<TableWithSearch data={this.props.data} updateCurrentItemId={this.updateCurrentItemId}/>)
            }
            else {
                show = (<DisplayItem />)
            }
    
            return (
                <React.Fragment>
                    <Row>
                        <Col>
                            { show }
                        </Col>
                    </Row>
                </React.Fragment>
            )
        }
        }
    }