Tibo
Tibo

Reputation: 763

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>
    )
}
}

Upvotes: 0

Views: 299

Answers (2)

gdh
gdh

Reputation: 13702

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>
        )
    }
    }
}

Upvotes: 1

partizanos
partizanos

Reputation: 1136

this.props should give you access for class components

In addition you should create a bind to the click function so it can correctly resolve this, in the constuctor of the rowEvent

Upvotes: 1

Related Questions