Почему при использовании setState (...) console.log имеет значение null? - PullRequest
0 голосов
/ 02 апреля 2020

Почему, когда я console.log (data) регистрирует данные, но когда я пытаюсь зарегистрировать элемент, заданный в установленном состоянии, его ноль? Я не понимаю, потому что у него нет времени на обновление до входа в консоль?

  const [currentUser, setCurrentUser] = useState(null);
        const [pending, setpending] = useState(true);
        const [userData, setuserData] = useState({});

        useEffect(() => {
            Authentication.auth().onAuthStateChanged((user) => {
                setCurrentUser(user)
                setpending(false)
                localStorage.setItem('user', user.uid);
                console.log(localStorage.getItem('user'));
            });

            getData()

        }, []);

        const getData = () => {
            Authentication.firestore().collection('Health_data')
                .doc(localStorage.getItem('user'))
                .get()
                .then(doc => {
                    const data = doc.data();
                    localStorage.setItem('user_data', JSON.stringify(data));
                    setuserData(data)
                    console.log(data)
                }).catch(function (error) {
                    console.error("Error reading health", error);
                });
                console.log(userData)
        }

Ответы [ 3 ]

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

Я предполагаю, что вы смущены выводом console.log(userData); в конце getData. Есть две причины, по которым он не показывает обновленного пользователя, одной из которых будет достаточно само по себе. :-) Это:

  1. console.log(userData) происходит перед setuserData вызовом, потому что обратные вызовы обещания всегда асинхронны.

  2. userData - константа в вызове функции Example, ее значение не изменится. Когда состояние будет изменено, Example будет вызван снова, и эта новая userData константа будет содержать обновленного пользователя. (Обратите внимание, что не имеет значения, объявлено ли оно с let или const, это фактически константа в любом случае.) Каждая из этих констант существует в контексте выполнения , который связан с указанным c вызов Example константа была создана в. Больше в статье Дана Абрамова Полное руководство по useEffect (что намного больше, чем useEffect).

Вот демонстрация:

const { useState } = React;

const delay = ms => new Promise(resolve => setTimeout(resolve, ms));

let executionContext = 0;
const Example = () => {
    const contextNumber = ++executionContext;
    const [value, setValue] = useState(0);

    const log = msg => console.log(`[${contextNumber}]: ${msg}`);

    log(`Example called, value = ${value}`);
    
    const onClick = () => {
        log(`onClick`);
        delay(800)
        .then(() => {
            const newValue = Math.floor(Math.random() * 10000);
            log(`calling setValue(${newValue})...`);
            setValue(newValue);
            log(`value is still ${value} (reason #2)`);
        });
        log(`value is still ${value} (reason #1)`);
    };
    
    return (
        <div>
            {value}
            <div>
                <input type="button" onClick={onClick} value="Click Me" />
            </div>
        </div>
    );
}


ReactDOM.render(<Example/>, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.12.0/umd/react-dom.production.min.js"></script>
1 голос
/ 02 апреля 2020

Если вы говорите об этом коде:

Authentication.firestore().collection('Health_data')
                .doc(localStorage.getItem('user'))
                .get()
                .then(doc => {
                    const data = doc.data();
                    localStorage.setItem('user_data', JSON.stringify(data));
                    setuserData(data)
                    console.log(data)
                }).catch(function (error) {
                    console.error("Error reading health", error);
                });
                console.log(userData)

Проблема в

Authentication.firestore().collection('Health_data')
                .doc(localStorage.getItem('user'))
                .get()

Это асинхронное c выполнение, поэтому console.log(userData) иногда будет выполняться перед Authentication вызов и значение будет null.

Таким образом, вы должны убедиться, что вызов Authentication завершен

0 голосов
/ 02 апреля 2020
if(userData !== null) {
    console.log(userData)
}

этот код, кажется, работает для меня, но я не уверен, как я могу использовать это для доступа к информации на других страницах таким же образом?

...