Состояние реакции не меняется после нажатия какой-либо кнопки

#javascript #reactjs #asynchronous #axios #event-handling

Вопрос:

После вызова handleButton , нажав Log In кнопку один раз, значение logInStatus пусто. Однако после второго щелчка значение logInStatus изменится. Я знаю, что setState-это асинхронный вызов, поэтому он не обновит значение logInStatus мгновенно. Как я должен подойти к решению?

 import React, {setState, useState, useEffect } from "react";
import Axios from "axios";
const Login = () => {
    useEffect(() => {
        document.title = 'Log In';
    });
    const [data, setData] = useState(null);
    const [username, setName] = useState('');
    const [password, setPassword] = useState('');
    const [logInStatus, setlogInStatus] = useState('');
    const user = [password,username]
    
    function read(user){
        let returned = checkRegister(user);
        returned.then(function(result) {
            setlogInStatus(result.data.message);
            //return setlogInStatus(result)
         });
    }

    const handleButton = (e) => {
        read(user);
        e.preventDefault();
        //logInStatus is empty here even it should contain soimething
        if(logInStatus == "Successfully Authenticated"){
            //do stuff
        }
     }
    function checkRegister(user) {
        const user_object = {
            username: user[1],
            password: user[0]
        }
        console.log(user_object)
        var ok;
            return Axios({
                method: "POST",
                data: user_object,
                withCredentials: true,
                url: "http://localhost:9000/users/login",
              });
    }
    return(
        
        <div className="login">
             <div>
      </div>
            <div className="userform">
            <h2 className="pagename">Log in</h2>
            <form>
                {/* <label>Username:</label> */}
                <input
                    type="text"
                    required
                    value={ username }
                    onChange={ (e) => setName(e.target.value) }
                    placeholder="Username"
                />
                {/* <label>Password:</label> */}
                <input
                    type="password"
                    required
                    value={ password }
                    onChange={ (e) => setPassword(e.target.value) }
                    placeholder="Password"
                />
                <button onClick={handleButton}>Log In</button>
                <h1>{logInStatus} </h1>
            </form>
            </div> 
        </div>
    );
}
export default Login;
 

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

1. Провели ли вы тест, чтобы setlogInStatus(result) непосредственно получить результат обещания axios? Потому что, с моей точки зрения, вы уже потребляете обещание с первым then входом checkRegister , поэтому у вас есть два решения, первое-это то, что я говорю выше, второе-вернуть обещание неиспользованным, удалив then вход checkRegister .

2. Можете ли вы указать строку, которая выдает ошибку?

3. @BenoitChassignol Вторым вариантом вы имеете в виду то, что я сделал выше(отредактировано)? Я удалил then checkRegister вход, но мне все равно нужно дважды нажать кнопку, чтобы получить измененные результаты logInStatus

4. @Yousaf , как сказано в ответе read , является обычной функцией, поэтому я не могу ее использовать then , поэтому я не должен был определять другую функцию. Но я все равно не смог решить эту проблему

5. @dogsht1338 да, именно это я и имею в виду. Теперь вы не должны видеть предыдущую ошибку, верно?

Ответ №1:

Отредактируйте, я не буду удалять первый абзац ниже, но это неправильно, используйте его в качестве контекста для комментария @Yousaf ниже.

Итак, чтобы продолжить, вы попытались then призвать обещание, которое уже было выполнено первым then , в которое вы вложили checkRegister . Что не может работать в связи с тем, как обрабатывать обещание, вы можете прочитать больше об этом здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise. Как я уже сказал, вам нужно выбирать между тем, потреблять его непосредственно в checkRegister свою функцию или потреблять после read нее. И установите состояние в соответствии с тем выбором, который вы делали раньше, где у вас есть доступ к вашему результату.

Вы должны поставить ключевое function слово перед checkRegister тем, как объявить его как оно.

Вы можете удалить var ok; то, что бесполезно и используется здесь. Вы также можете удалить вызванный импорт setState , который тоже не использовался.

И, наконец, вы можете удалить e.preventDefault(); то, что в вашем случае бесполезно, потому что вы используете простую кнопку, не связанную с вашей формой. Вы можете узнать больше о формах здесь: https://reactjs.org/docs/forms.html

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

1. «вы попытались вызвать тогда обещание, которое уже было выполнено первым тогда» then() метод также возвращает обещание, и возвращаемое им обещание разрешается значением, возвращаемым его функцией обратного вызова.

2. @Yousaf, вы правы, проблема этого кода заключалась в function ключевых словах, вот почему мы получаем Cannot read property 'then' of undefined . Только потому checkRegister , что не использовал function ключевое слово. Я отредактирую свой комментарий. Тнх.

Ответ №2:

В функции чтения убедитесь, что checkuser возвращает обещание.Вы можете использовать тогда и ловить только в случае обещаний js.Из вашего кода ясно, что checkuser-это не обещание, это просто функция, поэтому просто измените ее на обещание или иным образом удалите метод then. Проверьте это, чтобы узнать о обещаниях js