useEffect之后的异步运行功能

时间:2019-09-07 23:14:34

标签: javascript reactjs asynchronous react-hooks use-effect

我想知道在使用useEffect来获取数据后如何运行函数,而函数在提取数据后正在处理数据?

import React, { useState, useEffect } from 'react';

const Result = (props) => {
    const [ playerName, setPlayerName ] = useState('');
    const [ playerChoice, setPlayerChoice ] = useState(null);
    const [ computerChoice, setComputerChoice ] = useState(null);
    const [ result, setResult ] = useState(null);

    useEffect(() => {
        setPlayerName(props.location.state.playerName);
        setPlayerChoice(props.location.state.playerChoice);
        setComputerChoice(generateComputerChoice);
        setResult(getResult())
    }, []);

    const getResult = () => {
        // code that runs after the setting of the playerName and playerChoice. Will return "Win", "Lose", or "Draw"

    };

    const generateComputerChoice = () => {
        const outcomes = [ 'Rock', 'Paper', 'Scissors' ];
        return outcomes[Math.floor(Math.random() * outcomes.length)];
    };

    return (
        <div className="app-container">
            <strong>YOU {result}</strong>
            <br />
            <strong>{playerName}</strong> chose <strong>{playerChoice}</strong>
            <br />
            <strong>Computer</strong> chose <strong>{computerChoice}</strong>
        </div>
    );
};

export default Result;

因此,在此示例中,我从上一页抓取playerNameplayerChoice,然后在页面加载时将其添加到useState中。

此后,我随机生成computerChoice

但是,在那之后,我想使用已经添加到状态中的playerChoicecomputerChoice,并使用它来查看游戏是胜利,失败还是平局。

result最终成为null,因为我假设在调用getResult函数时,状态尚未设置。

你们知道在这种情况下应该怎么做吗?考虑到您可能想从API中获取数据,然后在想要呈现它之前对这些数据执行某些操作,似乎这很常见。

4 个答案:

答案 0 :(得分:0)

setState是异步的,您将只能在下一个渲染中使用该状态。与类组件不同,钩子在设置状态后不允许回调。

但是,查看组件并假设这就是组件的功能,就没有理由将playerName和playerChoice添加到组件的状态。您可以使用道具本身的数据。

SyntaxError

希望这会有所帮助。

答案 1 :(得分:0)

那第一个效果是不必要的。随便

  const [playerName, setPlayerName] = useState(props.location.state.playerName);

答案 2 :(得分:0)

使用useMemo挂钩并将状态变量添加到其依赖项数组中。它将记录每个渲染周期的结果,因此仅在playerNameplayerChoice更新时进行计算。

const getResult = useMemo(() => {
    // code that runs after the setting of the playerName and playerChoice. Will return "Win", "Lose", or "Draw"

}, [playerName, playerChoice]);

糟糕,我现在看到您正在尝试将其保存到result状态变量中,因此您可以使用具有相同依赖项的第二个useEffect代替我建议的useMemo,也可以在原始代码段中使用调用getResult()函数的过程中,将签名更改为getResult(name, choice)并使用当前渲染周期值(直接来自props)调用setResult。

useEffect(() => {
    const { playerName, playerChoice } = props.location.state;
    setPlayerName(playerName);
    setPlayerChoice(playerChoice);
    setComputerChoice(generateComputerChoice);
    setResult(getResult(playerName, playerChoice));
}, []);

const getResult = (name, choice) => {
    // Will return "Win", "Lose", or "Draw"
};

答案 3 :(得分:0)

谢谢大家的答复。最后,我重构为让计算机在上一个组件页面中生成选择,玩家也可以在其中进行选择。

这使得playerChoice和computerChoice都作为道具一起传递,这意味着可以使用数据而不必担心异步。

但是我对无论如何都可以解决此问题感兴趣。例如,如果我们从一个api调用,然后使用该api数据进行过滤(让我们按字母顺序或类似的方式对其进行排序),那么在useEffect api调用之后如何使用钩子来做到这一点?