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!!