biljohns
biljohns

Reputation: 33

Trying to pass event.target.name - TypeError: Cannot read property 'target' of undefined

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

Answers (2)

Manish Jangir
Manish Jangir

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

Shubham Khatri
Shubham Khatri

Reputation: 281626

There are few things you must keep in mind

  1. Synthetic Event data is cleared before callback and hence its not a good idea to pass the event directly and extract information from it.

  2. 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

Related Questions