1

我想知道如何在使用 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;

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

之后我随机生成computerChoice.

但是,在那之后,我想使用已经添加到状态中的playerChoiceAMD ,并使用它来查看游戏是赢、输还是平。computerChoice

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

大家知道在这种情况下应该怎么做吗?考虑到您可能想从 API 中获取数据,然后在渲染之前对这些数据进行处理,这似乎是一件很常见的事情。

4

3 回答 3

1

第一个效果是不必要的。做就是了

  const [playerName, setPlayerName] = useState(props.location.state.playerName);
于 2019-09-07T23:32:24.550 回答
0

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

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

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

const Result = (props) => {
    const {playerName, playerChoice} = props.location.state;
    const [ result, setResult ] = useState(null);
    const [computerChoice, setComputerChoice] = useState(null);

    useEffect(() => {
        setComputerChoice(generateComputerChoice());
        getResult();
    }, []);

    const getResult = () => {

     // You can get the playerName, playerChoice from the props.

     // You can also setResult here.

    };

    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;

希望这可以帮助。

于 2019-09-07T23:30:11.440 回答
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)当前渲染周期值(直接来自道具)调用 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"
};
于 2019-09-08T00:25:40.633 回答