My Home.js component just doesn't seem to see the dispatch function at all. Do you guys know why? I'm kinda new to redux style state management stuff in redux.
I keep getting the error "TypeError: dispatch is not a function"
App.js
import React from 'react';
import { HashRouter, Route } from 'react-router-dom';
import Home from './pages/Home';
import Start from './pages/Start';
import Result from './pages/Result';
import RPSContextProvider from './contexts/RPSContext';
const App = () => {
return (
<HashRouter>
<RPSContextProvider>
<Route exact path="/" component={Home} />
<Route path="/start" component={Start} />
<Route path="/result" component={Result} />
</RPSContextProvider>
</HashRouter>
);
};
export default App;
Home.js
import React, { useRef, useContext } from 'react';
import { RPSContext } from '../contexts/RPSContext';
import './home.css';
const Home = (props) => {
const { state, dispatch } = useContext(RPSContext);
const playerNameEntry = useRef();
const handleClick = () => {
if (!isStringEmpty(playerNameEntry.current.value)) {
dispatch({ type: 'SET_NAME', state: playerNameEntry.current.value });
props.history.push({
pathname: '/start'
});
console.log(dispatch);
}
};
const isStringEmpty = (string) => string.trim().length === 0;
return (
<div className="app-container">
<h1>
You dare battle me at
<br />
Rock, Paper, Scissors?
<br />
You got no chance, kid!
</h1>
<p>What's your name, ya chancer?</p>
<input type="text" onKeyPress={(e) => handleKeyPress(e)} ref={playerNameEntry} />
<button onClick={handleClick}>Start</button>
</div>
);
};
export default Home;
RPSContext.js
import React, { createContext, useReducer } from 'react';
import { RPSReducer } from '../reducers/RPSReducer';
export const RPSContext = createContext();
const RPSContextProvider = (props) => {
const [ state, dispatch ] = useReducer(RPSReducer, { playerName: '' });
return <RPSContext.Provider value={{ state, dispatch }}>{props.children}</RPSContext.Provider>;
};
export default RPSContextProvider;
RPSReducer.js
export const RPSReducer = (state, action) => {
switch (action.type) {
case 'SET_NAME':
return { playerName: action };
default:
throw new Error();
}
};
Basically as a first step I just want to set the name of the entry. I know this is quite a lot of code just for what I'm doing, but just wanting to try out useReducer and useContext so that I can learn all this new stuff in React.
const [state, dispatch] = useReducer(reducer, initialState); This hook function returns an array with 2 values. The first one is the state value, and the second value is the dispatch function which is further used to trigger an action with the help of array destructuring. Note: The “state” can be of any kind.
The dispatch is the second value returned from the useReducer Hook and can be used in our JSX to update the state: // creating our reducer function function reducer(state, action) { switch (action.
React useReducer doesn't support async actions natively. Unlike Redux, there's no middleware interface, but hooks are composable. This is a tiny library to extend useReducer's dispatch so that dispatching async actions invoke async functions.
React Context is a powerful state management feature in React. Instead of passing the props down through each component, React Context allows you to broadcast props to the components below. The useReducer hook is used for complex state manipulations and state transitions. …
I solved the problem by adding
switch (action.type) {
case 'SET_NAME':
return { ...state, playerName: action.payload }
in my reducer, and in Home.js changed the state key I had in there to payload. Not 100% sure if it having the same name was effecting anything, but its much less confusing naming it payload.
const handleClick = () => {
if (!isStringEmpty(playerNameEntry.current.value)) {
dispatch({ type: 'SET_NAME', payload: playerNameEntry.current.value });
Wrap the whole App with AppContext.Provider passing with state and dispatch, like below
<AppContext.Provider value={{ state, dispatch }}>
<div className="App">
<Compo />
</div>
</AppContext.Provider>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With