мое состояние не придает этому значения.

#reactjs #use-state #handle #use-ref #getstate

Вопрос:

Я добавил в свой код два обработчика. Сначала вводится почта и запускается handleStart, затем от пользователя получают имя пользователя и пароль, а затем при нажатии кнопки активируется handleFinish и выполняются назначения информации. Состояние setEmail работает, но состояния пароля и имени не работают

   const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [name, setName] = useState("");

  const history = useHistory();
  const url = "http://localhost:3002/register";

  const emailRef = useRef();
  const passwordRef = useRef();
  const usernameRef = useRef();

  const handleStart = () => {
        setEmail(emailRef.current.value);
      }
      const handleFinish = async (e) => {
        e.preventDefault();
        console.log("ref data", passwordRef.current.value,usernameRef.current.value) 
        //it works and shows values
        setPassword(passwordRef.current.value);
        setName(usernameRef.current.value);
        console.log("state data", email, password, name)
        //status values are empty except for email
        try {
          
          await axios.post(url, { email, name, password });
          history.push("/");
        } catch (err) { }
      }
 

и мои коды возврата (HTML) :

  {!email ? (
          <div className="input">
            <input type="email" placeholder="email address" ref={emailRef} />
            <button className="registerButton" onClick={handleStart}>
              Get Started
            </button>
          </div>
        ) : (
          <form className="input">
            <input type="username" placeholder="username" ref={usernameRef} />
            <input type="password" placeholder="password" ref={passwordRef} />
            <button className="registerButton" onClick={handleFinish}>
              Start
            </button>
          </form>
        )}
 

Ответ №1:

Лучше использовать useState для хранения и получения значений и элемента управления, а не использовать ref .

Вот код с использованием состояния, который может вам помочь:

 const App = () => {
    const history = useHistory();
    const url = "http://localhost:3002/register";

    const [step, setStep] = useState(0)
    const [email, setEmail] = useState("")
    const [password, setPassword] = useState("")
    const [username, setUsername] = useState("")

    const handleStart = () => {
        setStep(1)
    }
    const handleFinish = async (e) => {
        e.preventDefault();
        console.log("data: ", email, password, username)
        try {
            await axios.post(url, { email, name, password });
            history.push("/");
        } catch (err) { }
    }

    return (
        step === 0 ? (
            <div className="input">
                <input
                    type="email"
                    value={email}
                    onChange={(e) => setEmail(e.target.value)}
                    placeholder="email address"
                />
                <button className="registerButton" onClick={handleStart}>
                    Get Started
                </button>
            </div>
        ) : (
            <form className="input">
                <input
                    type="username"
                    placeholder="username"
                    value={username}
                    onChange={(e) => setUsername(e.target.value)}
                />
                <input
                    type="password"
                    placeholder="password"
                    value={password}
                    onChange={() => setPassword(e.target.value)}
                />
                <button className="registerButton" onClick={handleFinish}>
                    Start
                </button>
            </form>
        )
    )
}
 

Комментарии:

1. Теперь все работает, спасибо

Ответ №2:

Это очень хорошо известная проблема, объясняемая здесь тысячи раз, то,
что изменения состояния являются внутренне асинхронными , означает, что мы не получим обновленное состояние в следующей строке немедленно, требуется время для завершения выполнения setPassword и setName , поэтому следующая строка после заданного состояния, консоль.журнал будет иметь старые значения

 console.log(passwordRef.current.value)
console.log(usernameRef.current.value)
 

это должно иметь значения и войти в консоль, но нет password , и name
это приведенное ниже поведение является правильным, известным и здесь нет проблем,

  console.log("state data", email, password, name)
 //status values are empty except for email
 

лучше было бы, если бы этот приведенный ниже хак всегда работал на меня,

  await axios.post(url, { email, usernameRef.current.value, passwordRef.current.value });
 

Ответ №3:

Если вы хотите выполнить какое-либо действие, основанное на изменении значения электронной почты, пароля, имени, то использование useEffect может быть лучшим вариантом. Вы можете вызвать API или выполнить любое действие в результате изменения этих значений. Пожалуйста, найдите следующий код —

 useEffect(() => {
    await axios.post(url, { email, name, password });
    history.push("/");
    return () => {
        // handle cancelling or other clean up
    }
}, [email, password, name]);