karolis2017
karolis2017

Reputation: 2415

how to pass props to a component via onClick event?

Here I'm iterating through the list and displaying clickable {expense.createdAt}. When I click on the {expense.createdAt} I want to show its <ExpenseDetails /> on the same page, so I need to pass the props. How do I do that with onClick?

My code below which doesn't display anything.

class ExpenseList extends Component {

  render () {
    const {expenses} = this.props;
    const list = expenses.expenseList.map(expense =>
        <Segment clearing key={expense.uid} >
          <a href="" onClick={() => {this.passProps(expense)}}>
            {expense.createdAt}
          </a>
        </Segment>
    )

    const details = function passProps(expense){
      return (
        <div>
          <ExpenseDetails expense={expense}/>
        </div>
      )
    }

    return (
        <div>
          <Grid celled='internally'>
            <Grid.Row>
              <Grid.Column width={5}>
                <div>
                  <h1>Your Expense List:</h1>
                  <Segment.Group raised>

                    {list}

                  </Segment.Group>
                </div>

              </Grid.Column>
              <Grid.Column width={11}>
                <Segment>

                  {details}

                </Segment>
              </Grid.Column>
            </Grid.Row>
          </Grid>
        </div>

    )
  }
}

When I click on{expense.createdAt} the page refreshes. This might be an issue. How can I prevent that?

console.log(this.props.expenses):

enter image description here

Upvotes: 0

Views: 3458

Answers (1)

Andrew
Andrew

Reputation: 7545

Something like this should work. The important concept is that you need to have a parent to both of your subcomponents passing data. In this case, Expenses is the parent. In the parent, you create a function, showItemDetails that you pass down to ExpenseList. That is your clickhandler, which is used to pass back up the index location of the data you want to render. That showItemDetails then uses this.setState to give ItemDetails's the props you want.

import React, {Component} from 'react'

export default class Expenses extends Component {
  constructor(props) {
    super(props)
    this.state = {
      expenseItems: []
    }
  }

  showItemDetails(idx) {
    const {expenseItems} = this.props.expenses.expenseList[idx]
    this.setState({expenseItems})
  }

  render() {
    const createdDates = this.props.expenses.expenseList.map(({createdAt}) => {
      return createdAt
    })
    const expenseListProps = {
      showItemDetails: (idx) => this.showItemDetails(idx),
      createdDates
    }
    const itemDetailsProps = {expenseItems: this.state.expenseItems}
    return (
      <div>
        <ExpenseList {...expenseListProps}/>
        <ItemDetails {...itemDetailsProps}/>
      </div>
    )
  }
}

class ExpenseList extends Component{
  render() {
    const expenseList = this.props.createdDates.map((date, idx) => (
      <div key={idx}>
        <button onClick={() => this.props.showItemDetails(idx)}>
          {date}
        </button>
      </div>
    ))
    return (
      <div>
        {expenseList}
      </div>
    )
  }
}

class ItemDetails extends Component {
  render() {
    debugger;
    const items = this.props.expenseItems.map(({uid, date, desc, amount}) => (
      <div>
        {uid}
        {date}
        {desc}
        {amount}
      </div>
    ))
    return (
      <div>
        {items}
      </div>
    )
  }
}

Upvotes: 1

Related Questions