React Hooks: нет доступа к обновленной переменной useState - PullRequest
0 голосов
/ 02 апреля 2020

Проблема: inputVal - это переменная состояния, которую я обновляю с помощью setState.

Работает нормально, когда кнопка вызывает мою функцию handleConfirmSubmit.

Однако, если я добавлю eventListener, который прослушивает нажатие клавиши, то запускает функцию onKeyUp, которая затем запускает handleConfirmSubmit ... внезапно handleConfirmSubmit не может увидеть обновленное значение состояния.

Я добавил useEffect для выхода из консоли inputVal при вводе, и я могу подтвердить, что он обновляется, но по какой-то причине, в зависимости от того, где я вызываю handleConfirmSubmit, он может или не может видеть обновленное значение состояния.

КОД: (некоторые ненужные вещи удалены)

export default function SingleInputModal(props){
    const [cancelButton, setCancelButton] = useState(null);
    const [inputVal, setInputVal] = useState(props.previousValue || '');

    //ComponentDidMount
    useEffect( () => {

        //Listen for keypress
        window.addEventListener('keyup', onKeyUp);

        return () => {
            window.removeEventListener('keyup', onKeyUp);
        }
    }, []);

    useEffect( () => {
        console.log('new inputval', inputVal);
    },[inputVal])

    const handleChange = (e) => {
        console.log('handle Change ran', e.target.value);
        setInputVal(e.target.value || '');
    }

    const handleConfirmSubmit = () => {
        console.log('About to submit: ', inputVal);
        props.handleConfirmation(false, inputVal)
    }

    const onKeyUp = (e) => {
        if(props.submitOnEnter && e.key === 'Enter'){
            //Submit
            handleConfirmSubmit();
        }
        if(props.cancelOnESC && e.key === 'Escape'){
            //Cancel
            props.handleConfirmation(true, null);
        }
    }

    return(
        <div className="confirm"
        >
            <div className="modal singleInput"
            >
                <div className="content">
                    <input 
                        className='myModal__textInput'
                        type='text'
                        value={inputVal}
                        onChange={handleChange}
                    />
                </div>
                <div className="actions">
                        <a 
                        onClick={handleConfirmSubmit}
                        >Submit</a>
                </div>
            </div>
        </div>
    )
}

Ответы [ 2 ]

1 голос
/ 02 апреля 2020

Вы можете обновить слушателя при изменении inputVal, иначе слушатель сохранит копию значения inputVal из первого рендера.

useEffect( () => {

    //Listen for keypress
    window.addEventListener('keyup', onKeyUp);

    return () => {
        window.removeEventListener('keyup', onKeyUp);
    }
}, [inputVal]);
1 голос
/ 02 апреля 2020

Вы можете использовать React.useCallback, чтобы убедиться, что у вас есть бесплатные sh версии функций (поскольку, например, handleConfirmSubmit может захватить inputVal при его закрытии):

export default function SingleInputModal(props) {
  const [cancelButton, setCancelButton] = useState(null);
  const [inputVal, setInputVal] = useState(props.previousValue || "");

  useEffect(() => {
    window.addEventListener("keyup", onKeyUp);
    return () => window.removeEventListener("keyup", onKeyUp);
  }, []);

  useEffect(() => console.log("new inputval", inputVal), [inputVal]);

  const handleChange = e => {
    console.log("handle Change ran", e.target.value);
    setInputVal(e.target.value || "");
  };

  const handleConfirmSubmit = React.useCallback(
    () => {
      console.log("About to submit: ", inputVal);
      props.handleConfirmation(false, inputVal);
    },
    [inputVal],
  );

  const onKeyUp = React.useCallback(
    e => {
      if (props.submitOnEnter && e.key === "Enter") {
        // Submit
        return handleConfirmSubmit();
      }
      if (props.cancelOnESC && e.key === "Escape") {
        // Cancel
        props.handleConfirmation(true, null);
      }
    },
    [handleConfirmSubmit, props.submitOnEnter, props.cancelOnESC],
  );

  return (
    <div className="confirm">
      <div className="modal singleInput">
        <div className="content">
          <input className="myModal__textInput" type="text" value={inputVal} onChange={handleChange} />
        </div>
        <div className="actions">
          <a onClick={handleConfirmSubmit}>Submit</a>
        </div>
      </div>
    </div>
  );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...