3

Im trying to get compare a state from the node express server with the state in the redux store. If the state is different i want to update the store state to the same value as the server state. Now im getting the problem that I can not use these hooks in a non react function. I need this to work but ive looked up the redux documentation and as far as i understand these hooks can only be used in a react function component. Is there another way to still make this work since my whole application is based on the redux state already.

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

 /**
 * get the gamestate from the server
 * @returns {Promise<{data: any}>}
 */
async function getGamestate() {
    const gameStates = await fetch('http://localhost:3000/game-state').then(response => response.json());
    return {
        data: gameStates,
    }
}


export async function CheckIfChanged(){
    const serverGameState = await getGamestate();
    const clientGameState = useSelector(state => state.gameState);

    if(serverGameState.data !== clientGameState){
        console.log(serverGameState)
        //UpdateGameState(serverGameState)

    }else {
        console.log("still the same")
    }
}

Update: Im planning to call the function here in the mainview, this is basically a wrapper thats used in the whole application. The checkIfChanged function will be called every 5 seconds or so.

import React from 'react';
import '../../style/App.scss';
import Wrapper from '../wrapper/wrapper';
import StartView from '../startview/StartView';
import { useSelector } from 'react-redux';

function MainView(){

  const gameState = useSelector(state => state.gameState);

  //arround here i would call it and will be updating every 5 seconds later
  checkIfChanged();

  switch (gameState) {
    case "notStarted":
      return (
        <StartView/>
      );
    case "video":
    case "keypad":
    case "puzzle":
    case "completed":
    case "failed":
      return (
        <Wrapper/>
      );
    default:
    return (
      <div className="contentArea">
        <h1>Er is een fout opgetreden</h1>
      </div>
    );
  }

}
export default MainView;
2
  • Can you show how and where you use CheckIfChanged Commented May 19, 2020 at 9:52
  • @ShubhamKhatri At this point im testing if i could me this function work so im not really using it yet. However im planning to use it in my App.js which basically is the wrapper arround the whole application, I'll add it to the post Commented May 19, 2020 at 9:55

2 Answers 2

3

You can't define an async method with hooks directly in render. However you can convert your function in a custom hook which can then use useSelector and implement useEffect to sync your changes

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

 /**
 * get the gamestate from the server
 * @returns {Promise<{data: any}>}
 */
async function getGamestate() {
    const gameStates = await fetch('http://localhost:3000/game-state').then(response => response.json());
    return {
        data: gameStates,
    }
}


export function useCheckIfChanged(){ // not an async function
    const clientGameState = useSelector(state => state.gameState);
    const clientGameStateRef = useRef(clientGameState); 
    // Using a ref since we can't add clientGameState as a dependency to useEffect and it is bounded by closure

    useEffect(() =-> {
        clientGameStateRef.current = clientGameState;
    }, [clientGameState]);

    useEffect(() => {
          setInterval(async() => {
             const serverGameState = await getGamestate();
             // value inside here for clientGameState will refer to the original state only and hence we are using a ref which we update in another useEffect
             if(serverGameState.data !== clientGameStateRef.current){
                  console.log(serverGameState)
                 //UpdateGameState(serverGameState)

             }else {
                 console.log("still the same")
             }
          }, 5000)
    }, []);

}

import React from 'react';
import '../../style/App.scss';
import Wrapper from '../wrapper/wrapper';
import StartView from '../startview/StartView';
import { useSelector } from 'react-redux';

function MainView(){

  const gameState = useSelector(state => state.gameState);
  useCheckIfChanged(); // using the custom hook here

  switch (gameState) {
    case "notStarted":
      return (
        <StartView/>
      );
    case "video":
    case "keypad":
    case "puzzle":
    case "completed":
    case "failed":
      return (
        <Wrapper/>
      );
    default:
    return (
      <div className="contentArea">
        <h1>Er is een fout opgetreden</h1>
      </div>
    );
  }

}
export default MainView;
Sign up to request clarification or add additional context in comments.

Comments

0

You can update state by calling dispatch directly on store:

store.dispatch(actionName(values))

Redux documentation on handling store

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.