I want to dispatch a component prop as payload to my store from the click event of a sub-component:

const Aircraft = ({ ident, type, base, handleOnClick }) => (
    <div className="item" onClick={handleOnClick}>
        <i className="large plane middle aligned icon"></i>
        <div className="content">
            <div className="header">{ident}</div>
            <div className="description">{type}</div>
            <div className="description">{base}</div>
        </div>
    </div>
);

So I want to dispatch ident to handleOnClick.

The click event is passed as a prop from the parent component and mapped from a redux container.

const AircraftList = ({ aircraftList, setCurrentAircraft }) => (
    <div className="ui relaxed celled list">
        {aircraftList.map((el, index) => (
            <Aircraft key={index} {...el} handleOnClick={setCurrentAircraft} />
        ))}
    </div>
);

Redux container:

import { connect } from 'react-redux';
import AircraftList from '../../components/AircraftList/AircraftList';
import { setCurrentAircraft } from '../../actions/actions';

const mapStateToProps = state => {
  return {
    aircraftList: state.aircraft,
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    setCurrentAircraft: (e) => {
      dispatch(setCurrentAircraft(ident));
    }
  };
};

const AircraftListContainer = connect(
  mapStateToProps,
  mapDispatchToProps
)(AircraftList);

export default AircraftListContainer;

I am not sure how to pass the ident from the sub component to the dispatch and subsequently update the store?

2 Answers

3
GarVak On Best Solutions

If you need the event object inside setCurrentAircraft add the ident as a second argument, else keep ident as the only argument.

const mapDispatchToProps = (dispatch) => {
  return {
    setCurrentAircraft: (e, ident) => { // If `event` needed, else `(ident)`
      dispatch(setCurrentAircraft(ident));
    }
  };
};

Then wrap the handleOnClick on Aircraft inside another function to give it ident as an argument.

const Aircraft = ({ ident, type, base, handleOnClick }) => (
    <div className="item" onClick={(e) => handleOnClick(e, ident)}> // or just handleOnClick(ident)
        {/* ... */}
    </div>
);
1
adam.k On

Try this. You need to bind your click handler and dispatch the action from that. You also need to assign the ident value somewhere in you child component, so you can access it.

Redux Container

import { connect } from 'react-redux';
import AircraftList from '../../components/AircraftList/AircraftList';
import { setCurrentAircraft } from '../../actions/actions';
class AircraftListContainer extends React.Component {
constructor(props) {
super(props)
}
handleClick = (e) => {
const ident = e.currentTarget.getAttribute("data-ident")
this.props.setCurrentAircraft(ident)
}
render () {
return (<AircraftList aircraftlist={this.props.aircraftlist} handleClick= 
{this.handleClick} />)
  }
}
 const mapStateToProps = state => {
  return {
    aircraftList: state.aircraft,
  };
};
const mapDispatchToProps = (dispatch) => {
  return {
    setCurrentAircraft: (ident) => {
      dispatch(setCurrentAircraft(ident));
    }
  };
};

export default connect(mapStateToProps, 
mapDispatchToProps)(AircraftListContainer);

AircraftList

const AircraftList = ({ aircraftList, handleClick }) => (
    <div className="ui relaxed celled list">
        {aircraftList.map((el, index) => (
            <Aircraft key={index} {...el} handleOnClick={handleClick} />
        ))}
    </div>
);

Aircraft

const Aircraft = ({ ident, type, base, handleOnClick }) => (
    <div className="item" onClick={handleOnClick} data-ident={ident}>
        <i className="large plane middle aligned icon"></i>
        <div className="content">
            <div className="header">{ident}</div>
            <div className="description">{type}</div>
            <div className="description">{base}</div>
        </div>
    </div>
);