Aurimas
Aurimas

Reputation: 2727

How to correctly bind React onClick event with Redux?

Basically there's no sign that the event is binded somewhere and it's not firing. Here's the Component

class AgendaPointsList extends React.Component {
  constructor(props) {
    super(props);
    this.onAgendaPointClick = this.props.onAgendaPointClick.bind(this);
  }

  render() {
    let items = this.props.agenda_points.map((a, i) => {
      return <AgendaPoint key={i} agenda_point={a} index={i} onClick={this.onAgendaPointClick} />
    })

    console.log(this.props)

    return (
      <table>
        <tbody>
          {items}
        </tbody>
      </table>
    ); 
  }
}

The console.log(this.props) outputs:

Object
item_point: Object
item_points: Array[4]
onItemPointClick: onItemPointClick(id)
onModalCloseClick: onModalCloseClick(id)
store: Object
storeSubscription: Subscription
__proto__: Object

Here's the redux component:

const OPEN_AGENDA_POINT = 'meeting/OPEN_AGENDA_POINT'
const CLOSE_AGENDA_POINT = 'meeting/CLOSE_AGENDA_POINT'

const initialState = {
  modal_is_open: false,
  point_id: 0,
  point_data: {}
}

const openAgendaPoint = function (id) {
  return {
    type: OPEN_AGENDA_POINT,
    id: id
  }
}

const closeAgendaPoint = function (id) {
  return {
    type: CLOSE_AGENDA_POINT,
    id: id
  }
}

const agendaPointsReducer = function (state = initialState, action) {
  switch (action.type) {
    case OPEN_AGENDA_POINT: {
      state.modal_is_open = true,
      point_id = action.id
    }
    case CLOSE_AGENDA_POINT: {
      state.modal_is_open = false
    }
    default:
      return state
  }
}


const agendaPointsUiStateProps = (state) => {
  return {
    agenda_point: state.point_data
  }
}

const agendaPointsUiActions = (dispatch) => {
  return {
    onAgendaPointClick: (id) => {
      console.log(id)
      dispatch(openAgendaPoint(id))
    },
    onModalCloseClick: (id) => {
      dispatch(closeAgendaPoint(id))
    }
  }
}

const store = Redux.createStore(
  agendaPointsReducer, 
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)

// Usage:
const AgendaPointsList = connectWithStore(
  store, 
  AgendaPointsList, 
  agendaPointsUiStateProps, 
  agendaPointsUiActions
)

That's the child component:

class AgendaPoint extends React.Component {
  render() {
    return (
      <tr>
        <td>{ this.props.index + 1 }</td>
        <td>{ this.props.agenda_point.title}</td>
        <td>6</td>
        <td>{ this.props.agenda_point.agenda_time } min</td>
      </tr>
    ); 
  }
}

I tried multiple ways of binding the event:

onClick={this.props.onAgendaPointClick.bind(a.id, this)
onClick={this.props.onAgendaPointClick(a.id, this).bind(this)
onClick={() => this.props.onAgendaPointClick(a.id))

Non seem to work.

Using this for reac-redux connect wrapper to pass in store. This is running on Ruby on Rails Sprockets beta4.

What is the correct way of doing this?

Upvotes: 0

Views: 2868

Answers (2)

mahieus
mahieus

Reputation: 580

You want the on click to be on you tag. With the following code change you event will be triggerd:

class AgendaPoint extends React.Component {   render() {
    return (
      <tr onClick={this.props.onClick}>
        <td>{ this.props.index + 1 }</td>
        <td>{ this.props.agenda_point.title}</td>
        <td>6</td>
        <td>{ this.props.agenda_point.agenda_time } min</td>
      </tr>
    );    } }

Upvotes: 3

grizzthedj
grizzthedj

Reputation: 7505

Try binding the event in your ItemList constructor:

  constructor(props) {
    super(props);
    this.onItemClick = this.onItemClick.bind(this);
  }

Then in your ItemList render function ...

  let items = this.props.agenda_points.map((a, i) => {
    return <Item key={i} agenda_point={a} index={i} onClick={this.props.onItemClick} />
  })

This assumes that the onItemClick function is defined in ItemList parent, and is being passed in as a prop.

Upvotes: 1

Related Questions