0
votes

Here is my repo https://github.com/extrapractice/lambda-calculator/tree/revised

What is going on is when I am using a react hook for useState, it works fine, but however, I set up an event listener on useEffect for when a key is pressed (its a calculator) but for some reason once the key is pressed and the event is fired, the react state is undefined?

Why is this happening and how would I correct this?

const Calculator = (props) => {
const [ display, setDisplay ] = useState('');

useEffect(() => {
    window.addEventListener('keydown', handlekeyDown);
    // window.addEventListener('keydown', handleEquals);
    return () => {
        window.addEventListener('keydown', handlekeyDown);
        // window.addEventListener('keydown', handleEquals);
    };
}, []);

function handlekeyDown(e) {
    e.preventDefault();
    const current = e.key;
    const values = [ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '+', '-', '*', '/'];
    if (values.includes(current)) {
        let value = current;
        setDisplay((prev) => prev + value);
    }
}

 function handleEquals(e) {
    const value = e.key
    console.log(display)
    if (value === '=') {
        const solution = math.evaluate(display)
        const histEntry = { problem: display, solution: solution };
        props.setHistory((prev) => [ ...prev, histEntry ]);
        setDisplay(solution);
    }
}

function addToString(e) {
    console.log(e.target)
    let value = e.target.value;
    if (value === '=') {
        const histEntry = { problem: display, solution: math.evaluate(display) };
        props.setHistory((prev) => [ ...prev, histEntry ]);
        setDisplay(math.evaluate(display));
    } else {
        setDisplay((prev) => prev + value);
    }
}
1
Mind sharing all of the component code so it is easier to see what, where and when your display state is updated? Also, include the code for math.evaluate. FYI, you have a mistake in the return function of the effect, it should remove the event listener.Drew Reese
I looked in your repo for the whole component code, and also see math.evaluate is math.js and returns a number instead of a string. Trying to repro your issue but not successful yet. codesandboxDrew Reese
Nice catch about the event listener, the issue is solved and my solution is below, any idea why this works like this?Michael
Not really, no, as doing so would only trigger the effect each time handlekeyDown function was updated. Maybe it is because you define handlekeyDown after the effect, thus it is triggered with undefined, then once it becomes defined it's triggered again (now, since in dependency array). Doesn't seem likely this is the case though.Drew Reese
Interesting, I am newer to react hooks, so this is kind one of my introduction projects just to get familiar with them... will indeed try to look deeper into the code and see why it only works when included in the dependency array, thanks for your help Drew.Michael

1 Answers

1
votes

So what fixed this was adding the handleKeydown into the dependency array of the useEffect. The exact reason of why this is the case I have not narrowed 100% but I have a pretty solid idea.