React получил бесконечный цикл при использовании перехватчика useState() в файле макета

Получил проект в react-native + expo + react-native-web, мне нужно показать имя пользователя или ссылку для входа через файл макета в зависимости от того, хранится ли имя пользователя в хранилище.

приложение/_layout.tsx:

import React, {useState} from 'react';
import {SafeAreaView, StyleSheet, Text, View} from 'react-native';
import {Link, Slot} from "expo-router";
import Constants from "expo-constants/src/Constants";
import storageUtil from "@/utils/storage";
import constStorage from "@/constants/Storage";

export default () => {
  // username from storage, indicate whether already login,
  const [username, setUsername] = useState<string | null>(null);
  storageUtil.getItem(constStorage.keys.username).then(v => {
    console.info('username from storage: ', v)
    if (username !== v)  // add to avoid infinite loop, TODO: improve.
      setUsername(v)
  })

  return (
    <SafeAreaView style = {styles.container}>
      <View id='header' style = {{flex: 1}}><Text>
        {username ?
          (<Link href = "/home">{username}</Link>)
          : (<Link href = "/login">Login</Link>)
        }
      </Text></View>
      <View id='main' style = {{flex: 2, width: '100%', minHeight: 350, padding: 8}}>
        <Slot/>
      </View>
      <View id='footer' style = {{flex: 3}}><Text>Footer</Text></View>
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    paddingTop: Constants.statusBarHeight, // don't go to statusbar of phone,
    flex: 1,
    backgroundColor: '#FFF',
    position: 'relative',
    alignItems: 'center',
    justifyContent: 'center',
  },
})

Если я удалю строку if (username !== v) в браузере, когда я нажму ссылку username или Login, это вызовет бесконечный цикл.
ака. console.info('username from storage: ', v) Я вижу, как эта строка журнала в консоли Chrome печатается бесконечно быстро, а процессор загружен.

Итак, как избежать этого бесконечного цикла, кроме добавленного мной if (username !== v), что, на мой взгляд, не элегантно.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
1
0
53
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вызов storageUtil.getItem приводит к установке имени пользователя с помощью setUsername, что вызывает повторный рендеринг компонента, что вызывает вызов storageUtil.getItem, и снова и снова.

Чтобы предотвратить это, вам нужно использовать одноразовый useEffect

useEffect(() => {
  storageUtil.getItem(constStorage.keys.username).then(v => {
    setUsername(v);
  })
}, []);

Кажется, мне лучше использовать useEffect() без параметра , [], иначе после успешного входа в систему имя пользователя не отображается, вместо этого по-прежнему отображается ссылка для входа, что означает, что содержимое внутри useEffect() не выполняется при переходе из /login в /home через router.replace('/home');.

Eric 07.04.2024 13:37

Другие вопросы по теме

Похожие вопросы

Реагировать на перенаправление маршрутизатора dom V6 на двойной путь
Webauthn – Как проверить/проверить возвращенные данные аутентификации регистрации с помощью React + Node.js
Создание повторно используемых компонентов формы с использованием библиотеки Formik и Yup для React + Vite
Почему моя функция запроса React Query вызывается, хотя ее следует отключить?
Невозможно удалить по идентификатору из mongoDB в приложении nextjs
Значение в env prod не работает, проект vite
Coreui – Как правильно создать ссылку выхода (со значком) в нижнем колонтитуле (CSidebarFooter) боковой панели? (в React) Свернуть/развернуть проблему
Redux запрашивает несколько createApi и редуктора с повторной выборкой
Воспроизведение голосов, сгенерированных AWS-Polly, на стороне клиента в моем веб-приложении
ReactJS вызывает родительскую функцию из дочернего компонента, не показывая обновленное родительское состояние