Marcus Stancil
Marcus Stancil

Reputation: 3

How Should I Dispatch Actions When Using React Hooks?

I'm refactoring a React application to use hooks and have found some success, but I think I am incorrectly dispatching actions (using useReducer) within my application. I've discovered that the state doesn't change immediately when using hooks, and it's causing my application to behave differently than it's class-based counterpart. Here's a piece of my code that dispatches state in which I used console.logs to see if the state has changed or not. In both instances where state.gameOver is logged to the console, it's false, as well as state.userIsWrong. I've attached their actions my reducer as well. Thank you for the help in advance!

const wrongAnswer = () => {
  dispatch(toggleGameOver());
  console.log(`game over1 ` + state.gameOver)
  console.log('wrong answer')
  sounds["wrong"].play();

  //a delay is used to so that the header will return back to "Click me to begin game" or the current level of the game
  //and to return the background to normal
  setTimeout(() => {
    dispatch(toggleGameOver());
    console.log(`game over2` + state.gameOver)
    dispatch(turnOnUserIsWrong());
  },500)
}

turnOnUserIsWrong action from action.js

export const turnOnUserIsWrong = () => ({
type: 'TURN_ON_USER_IS_WRONG'

})

reducer.js

export default (state, action) => {
switch (action.type) {
    case 'SET_ACTIVE_STYLE':
        return {
            ...state,
            activeStyle: action.style
        }
    case 'UPDATE_LAST_COLOR':
        return {
            ...state,
            lastColor: action.color
        }
    case 'UPDATE_USER_PATTERN':
        return {
            ...state,
            userPattern: [...state.userPattern, action.id]
        }
    case 'UPDATE_GAME_PATTERN':
        return {
            ...state,
            gamePattern: [...action.newGamePattern]
        }
    case 'TOGGLE_PRESSED':
        console.log(action.color)
        return {
            ...state,
            pressed: action.color
        }
    case 'TURN_ON_READY_FOR_USER_INPUT':
        console.log(`here`)
        return {
            ...state,
            readyForUserInput: true
        }
    case 'TURN_OFF_READY_FOR_USER_INPUT':
        return {
            ...state,
            readyForUserInput: false
        }
    case 'RESET_GAME':
        return {
            ...state,
            gamePattern: [],
            userPattern: [],
            lastColor: "",
            level: 0,
            gameStarted: false,
            userIsWrong: false,
            readyForUserInput: false,
            activeStyle: '',
            strictRestart: false
        }
    case 'UPDATE_LEVEL':
        return {
            ...state,
            level: state.level + action.level
        }
    case 'TURN_OFF_USER_IS_WRONG':
        return{
            ...state,
            userIsWrong: false
        }
    case 'TURN_ON_USER_IS_WRONG':
            return{
                ...state,
                userIsWrong: true
            }
    case 'TOGGLE_STRICT_MODE':
        return {
            ...state,
            strictMode: !state.strictMode
        }
    case 'TOGGLE_GAME_STARTED':
        return {
            ...state,
            gameStarted: !state.gameStarted
        }
    case 'TOGGLE_GAME_OVER':
        return {
            ...state,
            gameOver: !state.gameOver
        }
    case 'EMPTY_USER_PATTERN':
        return {
            ...state,
            userPattern: []
        }
    case 'SET_PLAYER_LEVEL':
        return{
            ...state,
            level: action.level
        }
    default:
        return {
            ...state
        };     
}

}

Upvotes: 0

Views: 959

Answers (1)

Cesar Tomatis
Cesar Tomatis

Reputation: 599

Not sure how you're retrieving your state using hooks, but I'm currently working on a React App using only hooks, I'll leave you an example that I hope it helps you:

import React from 'react';
import { useDispatch, useSelector } from 'react-redux';

//YOUR OTHER IMPORTS

const YOURCOMPONENTNAME = (props) => {
   const gameOver = useSelector((state) => state.YOURREDUCERNAME.gameOver);

   const dispatch = useDispatch();
   const onToggleGameOver = () => dispatch(toggleGameOver());
   const onTurnOnUserIsWrong = () => dispatch(turnOnUserIsWrong());

   const wrongAnswer = () => {
      onToggleGameOver();
      console.log(`game over1 ` + gameOver)
      console.log('wrong answer')
      sounds["wrong"].play();

      //a delay is used to so that the header will return back to "Click me to begin 
      //game" or the current level of the game and to return the background to normal
      setTimeout(() => {
          onToggleGameOver();
          console.log(`game over2` + gameOver)
          onTurnOnUserIsWrong();
      },500)
   }

   // MORE CODE
}

export default YOURCOMPONENTNAME;

Not sure if this is of any help for you, hope it is. In case it´s not, I hope you find your answer!!

Upvotes: 1

Related Questions