React Hooks & Event Listener Trouble (useReducer, useContext, e.target)

Greetings! I am doing the React Drum Pad. I have put my actions in a reducer function (useReducer hook, NOT Redux). Then I put my state and dispatch data from useReducer into a Context provider and exported the data to the child components. I have a volume range switch, which is supposed to update the state on input by calling dispatch({type: ACTIONS.CHANGE_VOLUME} ) etc.

I get an error stating “Cannot read property ‘target’ of undefined.” It doesn’t seem to know what the event is. Here are the relevant parts of code:

Master Context:

import React, { useContext, useState, useRef, useReducer } from 'react';

export const GlobalStateContext = React.createContext();
export const DispatchContext = React.createContext();

export const ACTIONS = {
    TOGGLE_POWER: "togglePower",
    CHANGE_VOLUME: "changeVolume",
    TOGGLE_BANK: "toggleBank",
    TAP_KEY: "tapKey",
    CLICK_PAD: "clickPad",
    IS_PLAYING: "isPlaying",
    IS_NOT_PLAYING: "isNotPlaying"
}

export default function MasterProvider( { children } ){
    
/*syntax: const [state,dispatch] = useReducer(reducerFunction, initialStateValue)*/

const [state, dispatch] = useReducer(reducer, {isPowerOn: true, currentVolume: 0.5, kitOneIsActive: true, isPlaying: false});

function reducer(state, action){

    switch(action.type) {
        case ACTIONS.TOGGLE_POWER:
        return {...state, isPowerOn: !state.isPowerOn, isPlaying: false }
        case ACTIONS.CHANGE_VOLUME:
        return {...state, currentVolume: changeVolume()} //may need to test this
        case ACTIONS.TOGGLE_BANK:
        return {...state, kitOneIsActive: !state.kitOneIsActive}

        case ACTIONS.TAP_KEY:
        handleAudioKeyDown();
return {...state, isPlaying: false}

        case ACTIONS.CLICK_PAD:
        handleAudioClick();
        return {...state, isPlaying: false}

        case ACTIONS.IS_PLAYING:
            return {...state, isPlaying: true}

        case ACTIONS.IS_NOT_PLAYING:
            return {...state, isPlaying: false}

        default:
        return state;
    }
}

//IT DOESN'T KNOW WHAT E IS WHEN CALLED
function changeVolume(e) {
    console.log(e.target.value / 100);
    return e.target.value / 100;
};

return(
<GlobalStateContext.Provider value={{state, drumKitData}}>
            <DispatchContext.Provider value={dispatch}>
                {children}
            </DispatchContext.Provider>
     </GlobalStateContext.Provider>

);
}

FYI I wrapped my App in <MasterProvider></MasterProvider>.

Here’s my volume component:

import React, { useRef, useEffect, useContext } from 'react';
import './Volume.css';
import { ACTIONS, DispatchContext, GlobalStateContext } from './MasterContext';

export default function Volume(){

  const globalState = useContext(GlobalStateContext);
  const dispatch = useContext(DispatchContext);
  const state = globalState.state;

return (
        <div id="volume">
          <label htmlFor="volume-switch">Volume</label>
          <input
            id="volume-switch"
            name="volume-switch"
            type="range"
            min="0"
            max="100"
            value={state.currentVolume * 100}
            onInput={(e)=>dispatch({type: ACTIONS.CHANGE_VOLUME, payload: e})}
></input>
        </div>
      );
}

When I change the volume component (onInput), it throws the error “Cannot read property ‘target’ of undefined.” How do I make the external dispatch function in my reducer understand what e is? Do I need to add an event listener or something?

I know this is long, so thank you for your help!!

I figured it out!! I forgot to put my payload on the function in my switch statement. So in my switch statement this is what I have coded now:

function reducer(state, action) {

    switch(action.type) {
        ///
        case ACTIONS.CHANGE_VOLUME:
        return {...state, currentVolume: changeVolume(action.payload)}
        ///
    }
}

Now it works. Hooray!

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.