Home > Blockchain >  State is always blank
State is always blank

Time:12-06

I'm new to React and trying to understand why my state value is blank. In my component, I have a state for the HTML input element. When I put a console log on the function "searchChange" handler it is properly receiving my keyboard entries. But when I click on the enter key the value of "searchState" is blank. So I'm wondering what is wrong with my code?

export default (props: any, ref: any) => {

    const SearchNavigation = forwardRef((props: any, ref: any) => {

    const [searchState, setSearchState] = React.useState('');
    const searchChange = (evt: React.ChangeEvent<HTMLInputElement>) => {
        console.log(`Input ${evt.target.value}`);
        setSearchState(evt.target.value);
    };

    function enterHandler(evt: any): any {
        if ((evt.which && evt.which === 13) || (evt.keyCode && evt.keyCode === 13)) {
            console.log(`Enter value ${searchState}`);
            return false;
        }
    }

    useEffect(() => {
        document.body.addEventListener('keypress', enterHandler);

    }, []);

    return (
        <section id={props.id} className="is-shadow-d2">
            <input type="text" onChange={searchChange} />
        </section>
    );
}

If I add the following hook, it is logging my value of "searchState" properly as I type each letter, but I want to use the value when the users clicks on the enter key.

useEffect(() => {
    console.log(`State Changed: ${searchState}`);
}, [searchState]);

Update

So I modified my code to handle a keypress on the input and seems to work.

const searchKeyPress = (evt: React.KeyboardEvent) => {
    if (evt.key === 'Enter') {
        console.log(`Enter value ${searchState}`);
    }
};
....
<input type="text" onChange={searchChange} onKeyPress={searchKeyPress} />

And now its showing the values. But what I'm wondering about is if I want to have a global enter key to do something like save the data but the states values are blank, what is the best way to handle that?

CodePudding user response:

useEffect(() => {
  document.body.addEventListener('keypress', enterHandler);
}, []);

The empty dependency array says that this effect should be run once, and then never again. At the time that the effect runs, searchState is an empty string, and so enterHandler closes over that empty string. Since the functions never get updated, it will still see an empty string when the keypress occurs.

Instead, you can change it to update when the searchState changes like this:

useEffect(() => {
  function enterHandler(evt: any): any {
    if ((evt.which && evt.which === 13) || (evt.keyCode && evt.keyCode === 13)) {
      console.log(`Enter value ${searchState}`);
      return false;
    }
  }
  document.body.addEventListener('keypress', eventHandler);
  return () => {
    document.body.removeEventListener('keypress', eventHandler);
  }
}, [searchState]);

CodePudding user response:

The issue is that states are not accessible in the context of event listeners.

You can find an answer to this problem here: Wrong React hooks behaviour with event listener

  • Related