Donatas
Donatas

Reputation: 25

Unable to execute passed function in React component

I have a React component ResultsTable with markup only, and all data fetching is done in its container ResultsTableContainer and passed when rendering.

ResultsTable.jsx

const ResultsTable = ({ games, results }) => (
<Table>
<TableHeader>
  <TableRow>
    <TableHeaderColumn>Date</TableHeaderColumn>
    <TableHeaderColumn>City</TableHeaderColumn>
    <TableHeaderColumn>Venue</TableHeaderColumn>
    <TableHeaderColumn>Host</TableHeaderColumn>
  </TableRow>
</TableHeader>
<TableBody>
  {games.map((game, index) => (
    <TableRow key={index} onClick={(index) => results}>
      <TableRowColumn>
        {moment(game.gameDate).format("YYYY-MM-DD")}
      </TableRowColumn>
      <TableRowColumn>{game.city}</TableRowColumn>
      <TableRowColumn>{game.venueName}</TableRowColumn>
      <TableRowColumn>{game.hostName}</TableRowColumn>
    </TableRow>
  ))}
</TableBody>
</Table>
);

export default ResultsTable;

ResultsTableContainer.jsx

class ResultsTableContainer extends Component {
constructor(props) {
super(props);

this.state = {
  games: []
};
}

componentDidMount = () => {
 axios
  .get("public_api/games")
  .then(resp => {
    this.setState({
      games: resp.data
    });
  })
  .catch(console.error);
 };

handleClick = (i) => {
console.log('clicked' + i)
};

render() {
return (
  <ResultsTable
    games={this.state.games}
    results={this.handleClick.bind(this)}
  />
   );
 }
}

export default ResultsTableContainer;

My challenge is to make each table row clickable, that I can get more information when clicked on the row. However writing this way, does not execute function handleClick and from what I have read also is not the best way to do things, as it will create a new function for each row. So my question would be how can I create onClick handler for that would know which row have I clicked? Or what else may I do to make it work? Also, would really appreciate, if you could point me to a good reading about this topic. Thank you!

Upvotes: 0

Views: 82

Answers (2)

Donatas
Donatas

Reputation: 25

Seems it was related to a bug in Material UI Table component, which I am using. More info: https://github.com/callemall/material-ui/issues/1783 . So I ended up creating button for each row and now everything works.

Upvotes: 0

bennygenel
bennygenel

Reputation: 24660

Since you are already using an arrow function for handleClick you don't need bind the function again manually. You can just use it as this.handleClick.

To get the index/id of the row you clicked you can try something like this,

const ResultsTable = ({ games, onRowClick }) => (
<Table>
<TableHeader>
  <TableRow>
    <TableHeaderColumn>Date</TableHeaderColumn>
    <TableHeaderColumn>City</TableHeaderColumn>
    <TableHeaderColumn>Venue</TableHeaderColumn>
    <TableHeaderColumn>Host</TableHeaderColumn>
  </TableRow>
</TableHeader>
<TableBody>
  {games.map((game, index) => (
    <TableRow key={index} id={index} onClick={onRowClick}>
      <TableRowColumn>
        {moment(game.gameDate).format("YYYY-MM-DD")}
      </TableRowColumn>
      <TableRowColumn>{game.city}</TableRowColumn>
      <TableRowColumn>{game.venueName}</TableRowColumn>
      <TableRowColumn>{game.hostName}</TableRowColumn>
    </TableRow>
  ))}
</TableBody>
</Table>
);

export default ResultsTable;

class ResultsTableContainer extends Component {
constructor(props) {
super(props);

this.state = {
  games: []
};
}

componentDidMount = () => {
 axios
  .get("public_api/games")
  .then(resp => {
    this.setState({
      games: resp.data
    });
  })
  .catch(console.error);
 };

handleClick = (event) => {
  // event object from the onClick of the row will be passed
  // you can get the index of the row from the event target's id prop
  // rather than index, you can use an unique id of some sort too
  console.log(`clicked on row ${event.target.id}`);
};

render() {
return (
  <ResultsTable
    games={this.state.games}
    onRowClick={this.handleClick}
  />
   );
 }
}

export default ResultsTableContainer;

Upvotes: 1

Related Questions