Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
200 views
in Technique[技术] by (71.8m points)

javascript - Updating a state variable inside of a react function

I'm using the State Hook to update a Throttle setting for a robot based on keyboard commands (W,A,S,D). I have a maxThrottle state variable that ensures that the robot doesn't go too fast. However, I am using a slider to adjust the maxThrottle command. When you press the W key (forward) you should get the current maxThrottle['forward'] value assigned to the throttleCommand variable. However, every time the handleKey function runs, I just get throttleCommand['forward'] set to the initial value of 30, even if I have changed maxThrottle (using setMaxThrottle) to a higher number like 80.

function App(){

//state hooks
    const [ throttleCommand, setThrottleCommand ] = useState({ forward: 0, turn: 0 });
    const [ maxThrottle, setMaxThrottle ] = useState({ forward: 30, turn: 15 });

useEffect(
        () => {
            sendThrottle(throttleCommand);
        },
        [ throttleCommand ]
    );

    const handleKey = (e) => {
        switch (e.code) {
            case 'KeyW':
                setThrottleCommand({ ...throttleCommand, forward: maxThrottle.forward });
                break;
            case 'KeyS':
                //THIS SHOULD TURN IT OFFF
                setThrottleCommand({ forward: 0, turn: 0 });
                break;
            case 'KeyA':
                //turn left
                setThrottleCommand({ ...throttleCommand, turn: -maxThrottle.turn });
                break;
            case 'KeyD':
                setThrottleCommand({ ...throttleCommand, turn: maxThrottle.turn });
                break;
            default:
                break;
        }
    };


    const sendThrottle = () => {
        //here I test the throttleCommand
        console.log('sending command', throttleCommand);
        axios.get(`/throttle/${throttleCommand.forward}/${throttleCommand.turn}`).then((res) =>    {
            setThrottleData(res.data);
        });
    };

....

}

I have verified that I successfully update maxThrottle to {forward:80,turn:20} but when I press the W key, the throttleCommand is logged as {forward:30, turn:0}. I am expecting to see {forward:80,turn:0} assigned to throttleCommand.

Is there something wrong with using a state variable inside the handleKey function? Why am I always getting the initial value of maxThrottle assigned to throttleCommand?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Michael Bauer! Thanks for the fix. You are 100% correct. Code now works. here is the change:

incorrect keydown listener:

    useEffect(() => {
        document.addEventListener('keydown',handleKey);
    }, []);

SOLVED / CORRECT keydown listener

    useEffect(() => {
        document.addEventListener('keydown', (e) => {
            handleKey(e);
        });
    }, []);

Lesson learned - use arrow functions inside of useEffect so that the callback function updates!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...