Reputation: 33
I have been working with React for a few months on a new project and recently decided to implement Redux (still new to it).
getMusicGenreOptions function worked prior to adding it to the reducer/implementing redux. I am not sure how to pass 'event' (specifically event.target.name) on dispatch to the reducer function so it does not return undefined (onClick).
My error:
TypeError: Cannot read property 'target' of undefined
My code:
The Click Event
<button
className="categories"
name="blue note"
onClick={(event) =>
{
event.preventDefault();
this.props.getMusicGenreOptions(event);
}
}
>blue note
</button>
The Dispatch
const mapDispatchToProps = (dispatch, event) => {
return {
getMusicGenreOptions: (event) =>
dispatch({
type: 'GET_MUSIC_GENRE_OPTIONS',
}),
}
}
The Reducer
export const reducerInterestForm = (state = initialState, action) => {
switch (action.type) {
case "GET_MUSIC_GENRE_OPTIONS":
const genre = event.target.name; // get the name of the music genre via event target
const music = data.interest.filter( music => music.category === "music" ); // filter music specific interest into an array (no movies or television)
const filteredOptions = music.find( options => options.group === genre); // filter out the specific genre via event target
return Object.assign({}, state, {
currentMusicGenre: this.state[filteredOptions.state]
})
Upvotes: 1
Views: 566
Reputation: 5437
As per @Subham's statement in his answer, You should never use the event data outside of the callback function in react as Synthetic Events in React are pooled for performance reasons. Event pooling means, once the event handler or callback is invoked, the event properties are nullified hence they cannot be used for future usage.
now coming back to your original question, you are not passing any action payload along with the action type in your mapDispatchToProps to a redux action. Pass it in the dispatch like below:
const mapDispatchToProps = dispatch => ({
getMusicGenreOptions: name => dispatch({
type: 'GET_MUSIC_GENRE_OPTIONS',
name
})
});
Always try to keep redux payloads and state data as much as plain objects to make it work in isolation. Right now in your code, the redux part is getting dependent on your react events which is not a good practice.
Upvotes: 0
Reputation: 281626
There are few things you must keep in mind
Synthetic Event data is cleared before callback and hence its not a good idea to pass the event directly and extract information from it.
You must pass the data while calling dispatch
Code:
<button
className="categories"
name="blue note"
onClick={(event) =>
{
event.preventDefault();
this.props.getMusicGenreOptions(event.target.name);
}
}
>blue note
</button>
const mapDispatchToProps = (dispatch, event) => {
return {
getMusicGenreOptions: (name) =>
dispatch({
type: 'GET_MUSIC_GENRE_OPTIONS',
name
}),
}
}
switch (action.type) {
case "GET_MUSIC_GENRE_OPTIONS":
const genre = action.name; // get the name of the music genre
const music = data.interest.filter( music => music.category === "music" ); // filter music specific interest into an array (no movies or television)
const filteredOptions = music.find( options => options.group === genre); // filter out the specific genre via event target
return Object.assign({}, state, {
currentMusicGenre: this.state[filteredOptions.state]
})
Upvotes: 2