1
votes

I have next component:

const [username, setUsername] = useState('');
const [password, setPassword] = useState('');

const handleUserKeyPress = useCallback((event) => {
    if (event.keyCode === 13) {
      doLogin({ username, password }, loginDispatch, callback);
    }
  }, []);

  useEffect(() => {
    window.addEventListener('keypress', handleUserKeyPress);
  }, [handleUserKeyPress]);

      <ProjectFormField
        label={t('email')}
        formInputProps={{
          value: username,
          onChange: (event) => setUsername(event.target.value),
        }}
        inputType="email"
      />

      <ProjectFormField
        label={t('password')}
        formInputProps={{
          value: password,
          onChange: (event) => setPassword(event.target.value),
        }}
        type="passwordField"

      />

     <Button
        label={'loginEnter'}
        id="login-button"
        disabled={ !username || !password}
        onClick={() => {
          doLogin({ username, password });
        }}
        
      />

     

***Where ProjectFormField is our custom app wrapper for Material ui text field component

When I do click on button the values of username and password exists in state. When I press the enter button, the callback function is working, but values in state are empty. I also tried solution with userRef, where the ref was the wrapper container of login component, but the result was the same. What I am doing wrong?

2
So, if I understand correctly, you fill your form, hit enter, and when the callback gets called, your state is empty, despite the form having been filled. Is that right? - Adrian Pascu
The state parameters (username and password) aren't updated within handleUserKeyPress, since it's a function using the useCallback hook. You could add username and password to the useCallback dependency array, which would update the callback each time either of them changes. But I wouldn't recommend for performance reasons. - Luuuud
@AdrianPascu yes indeed - AlexBerd
@LuudJacobs this one is working, but I have 3 callback calls: 1) still with empty states, 2) username is filled, password is empty, 3) state is filled.... is it right behaviour for such simple form? Can this one be avoided? - AlexBerd
I think@LuudJacobs is right. You could also not use useCallback. Since it's a login form, memoization shouldn't improve performance too much. - Adrian Pascu

2 Answers

0
votes

you might want to use useRef hook here. Here is the codesandbox link you can refer: https://codesandbox.io/s/exciting-framework-mprqg?file=/src/index.js

0
votes

I was having the same issue today & once in the last week, which I postponed. Saw this question & answer. Then found this github reply.

There I saw an example about how useRef can be used. I found it as making things complex. However, in the end he outlines about passing a function to setState function to update the values. It worked great!

In my case it was like this:

const [posts, setPosts] = useState([]);

useEffect(function onLoad() {
  
  const unregisterEventListener = listenToNewPostEvent();

  return unregisterEventListener;

}, []);

function listenToNewPostEvent() {
  
  function handleNewPost(post) {
    // "posts" is empty in this line. 
    // Calling setPosts([post, ...posts]) always left "posts" with one entry.
    // So, I changed as follows as mentioned in the previously given link.
    setPosts(function updatePosts(posts) {
      // Here "posts", which is coming as parameter to this function is the latest one.
      return [post, ...posts];
    });
    // Now the posts array has the latest data & the same gets reflected in the screen as well.
  }

  return eventSystem.on(NEW_POST, handleNewPost);

}