0

I had read a lot of answers of questions about it, but it didn't helped me.
Functional component need once subscribe to events and get data from API to state.
But state don't changes correctly.

const [games, setGames] = useState(null);
const [activeGame, setActiveGame] = useState(null);
const [pending, setPending] = useState(false);

useEffect(() => {
    if (games === null) {
        setPending(true);
        API.Game.get({}).then((res) => {
            if (res.success) {
                console.log(res.msg.games) // Returning array of games [{...}, {...}]

                setGames(res.msg.games);
                setActiveGame(res.msg.activeGame);

                // Rendered games, but didn't changed state :/
                setTimeout(() => console.log(games), 1000) // Returning null (initial state)
            }
            setPending(false);
        });

        API.Socket.emit('subscribe', 'game');
        API.Socket.on('addGame', (game) => {
            setGames((games) => [...games, game]);
        });
        API.Socket.on('open', (isReconnect) => {
            if (isReconnect) API.Socket.emit('subscribe', 'game');
        });
    }
}, [games, pending, activeGame]);

Depending on answers you provided, I tried this, but it still don't work.

const [games, setGames] = useState([null]);
const [activeGame, setActiveGame] = useState(null);
const [pending, setPending] = useState(false);

const fetchGames = async () => {
    setPending(true);
    const res = await API.DurakGame.get({});
    if (res.success) {
        setGames(res.msg.games);
        setActiveGame(res.msg.activeGame);
    }
    setPending(false);
    return true;
};

useEffect(() => {
    fetchGames();

    API.Socket.emit('subscribe', 'durak');
    API.Socket.on('addGame', (game) => {
        setGames((games) => [...games, game]);
    });
    API.Socket.on('open', (isReconnect) => {
        if (isReconnect) API.Socket.emit('subscribe', 'durak');
    });
}, []);
iosrat
  • 50
  • 7
  • after setGames, games value still is null – iosrat Jun 11 '20 at 09:40
  • State updates with hooks are not just async but are also affected by closures and hence you don't see the updated value in the same render cycle even if you add a setTimeout. Please check the duplicate for more detailed explanation and a solution – Shubham Khatri Jun 11 '20 at 10:04
  • It didnt help me. I tried a lot of variations, depending on this question before creating this one. This question dont solve the problem. – iosrat Jun 11 '20 at 10:12
  • There is no problem, the state is updated, its not just seen in the same render cycle. If you log the state in useEffect with a dependency on games, you will see the update – Shubham Khatri Jun 11 '20 at 10:13
  • No update of state. Also I provided the state into other component in render. Several code lines up it renders, but providing empty array to other component. – iosrat Jun 11 '20 at 10:16
  • Did you try and add `useEffect(() => { console.log(games); }, [games])` in your component by following the second approach. It definitely will show you the update – Shubham Khatri Jun 11 '20 at 10:19
  • Yes, but how to move this state into component in render? it don't work. – iosrat Jun 11 '20 at 10:31
  • It will work, you can log the prop in display component directly, it will show the update. It will be null initially since your useState is initialised with null but will update in the next render – Shubham Khatri Jun 11 '20 at 10:33

1 Answers1

0

Possibility that problem can be caused by :

  1. Maybe API function that you is used is async ?
    If yes, useEffect parameter callback is not async and can't be async maybe :D. Reference React Hooks.
    Solution : You can use sperate function API async and call on useEffect function.
    Maybe you can refer on this link Example For useEffect async
  2. The data state updated is Array types
    State data type is immutable, that means you can't modify directly on the state (Different allocation memmory). And array type is one of data type that if the variable is assigmented on other can have different allocation.
    So you should be destruct the data for manipulating the data that can be same allocation.
    React State with array

I hope that answered your question. Thanks before

illusi03
  • 51
  • 1
  • 7