Слишком много повторных рендеров. React ограничивает количество отрисовок, чтобы предотвратить бесконечный цикл для собственного кода React в моем коде в асинхронном компоненте без состояния

#reactjs #react-native

Вопрос:

Столкнулся со слишком большим количеством повторных рендеров. React ограничивает количество отрисовок, чтобы предотвратить бесконечный цикл для собственного кода React в моем коде в асинхронном компоненте без состояния.

Я пытаюсь вызвать асинхронный метод, используя компонент без состояния. Я пытаюсь вызвать API внутри асинхронного хранилища.

Поэтому в основном мне нужно получить электронное письмо от Asyncstorage и передать эту ссылку в API. Я пытаюсь это сделать, но получаю ошибку, сталкиваясь со Слишком большим количеством повторных рендеров. React ограничивает количество рендеров, чтобы предотвратить бесконечный цикл

 import { BottomNavigation, Text } from 'react-native-paper';
import HomeScreen from './Home';
import PatientScreen from './Patient';
import OtpScreen from './Otp';
import Settings from './settings';
import SearchDoctor from './SearchDoctor';


const PatientPage = ({ navigation }) => {
    const [expanded, setExpanded] = React.useState(true);
    const [index, setIndex] = React.useState(0);
    const [text, setText] = React.useState({
        email: ''
    });
    const [routes] = React.useState([
        { key: 'music', title: 'Music', icon: 'queue-music' },
        { key: 'search', title: 'Search', icon: 'magnify' },
        { key: 'settings', title: 'Settings', icon: 'cog-outline' },
    ]);

    const getData = async () => {
        if (!expanded)
            try {
                AsyncStorage.getItem('@storage_Key').then((data) => {
                    let value = JSON.stringify(data);
                    setText({
                        ...text,
                        email: value.email
                    })
                    fetch("http://localhost:8090/patient/fetchData", {
                        method: "POST",
                        headers: {
                            "Content-type": "application/json; charset=utf-8",
                        },
                        "body": JSON.stringify({
                            email: text.toShowLoginEmail
                        })
                    }).then(response => response.json()).then(response => {
                        console.log(response);
                    })
                })
            } catch (e) {
                // error reading value
            }
    }

    const handleValidUser = () => {
        setExpanded(true);
        getData();
    }

    handleValidUser();

    const renderScene = BottomNavigation.SceneMap({
        music: HomeScreen,
        search: SearchDoctor,
        settings: Settings,
    });

    return (
        <BottomNavigation
            navigationState={{ index, routes }}
            onIndexChange={setIndex}
            renderScene={renderScene}
        />
    );
}

export default PatientPage;```
 

Ответ №1:

Проблема в том, что Вы вызываете handleValidUser(); тело компонента, и транс происходит вот так handleValidUser() -> getData() -> setText() .

Так handleValidUser вызывается при каждом рендеринге, но сама функция изменяет состояние, что вызывает повторный рендеринг и другой вызов handleValidUser , создавая таким образом цикл

рассмотрите возможность использования useEffect для вызова функции только один раз или только при изменении определенных зависимостей

 // Don't forget to import { useEffect } from 'react'
useEffect(() => {
 handleValidUser();
}, []);
 

В этом случае массив зависимостей пуст, поэтому функция будет вызвана только один раз, когда компонент монтируется (очень похоже componentDidMount . Для более сложного использования массива зависимостей см. раздел React useEffect.

По-видимому, существуют некоторые зависимости, поэтому следующее может помочь.

 const getData = React.useCallback(async () => {
          if (!expanded){
            try { .... 
          }
        }, [expanded]); //add expanded as a dependency
 
 const handleValidUser = React.useCallback(() => {
        setExpanded(true);
        getData();
    }, [setExpanded, getData)
 

Наконец, измените крючок useEffect

 useEffect(() => { 
  handleValidUser() 
}, [handleValidUser]);
 

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

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

1. Попробовал, эта ошибка исчезла, но API еще не вызывается при загрузке

2. Это потому if(!expanded) , что не сработает. Я изменю код, пожалуйста, попробуйте это.

3. Да, пожалуйста, внесите изменения и поблагодарите меня. Я совсем новичок в реагировании на родной язык