Почему я получаю следующее предупреждение React Native: не удается выполнить обновление состояния React для не подключенного компонента - PullRequest
0 голосов
/ 17 марта 2020

Я пытаюсь создать приложение React Native, но я все еще новичок в экосистеме React / RN, так что, возможно, я просто неправильно понимаю что-то очевидное в проблеме, с которой я столкнулся.

I есть приложение, в котором многие страницы структурированы следующим образом:

<View>
    <NavComponent />
    <View>
        {/* Page component structure/logic here */}
    </View>
</View>

NavComponent загружает переключаемое навигационное меню с TouchableOpacity элементами, такими как:

Go to Screen #1
Go to Screen #2
Go to Screen #3

У меня проблема (и, возможно, это не проблема, а только то, как работает React / RN) в том, что если я запускаю на экране № 1, откройте навигацию, go на экране № 2, снова откройте навигацию , а затем go обратно на экран # 1, хотя экран # 1 снова появляется, реальная функция рендеринга для экрана # 1, кажется, не вызывается снова, и, поскольку NavComponent является частью рендеринга каждого На экране, когда я снова пытаюсь открыть навигацию с экрана # 1, я получаю следующее предупреждение:

Предупреждение: не удается выполнить обновление состояния React для не подключенного компонента. Это неоперация, но она указывает на утечку памяти в вашем приложении. Чтобы исправить, отменить все подписки и асинхронные задачи в% s.% S, функция очистки useEffect ...

Опять же, возможно, мой подход к приложению изначально некорректен, но, по сути, когда Я go с одного экрана на другой с навигационной панели, я всегда хочу, чтобы новый экран заново рендерился с нуля (включая начальный Ajax вызов данных).

Вот более конкретный пример функции рендеринга для экрана (все они следуют одному и тому же шаблону basi c):

const screen1 = ({ navigation }) => {
    const [serverData, setServerData] = useState(null);

    useEffect(() => {
        // getPageData is a custom method I added to axios.
        axios.getPageData('/api/url/here', (data) => {
            setServerData(data);
        });
    }, []);

    if (serverData) {
        const { meta, user, data } = serverData;

        return (
            <View>
                <NavComponent />
                <View style={styles.container}>
                    {/* Page component structure/logic here */}
                </View>
            </View>
        );
    }

    return null;
};

Если, например, я добавил console.log в начало функции рендеринга выше, это вызывается при первой загрузке экрана, но если я go на экране № 2, а затем возвращаюсь на экран № 1 через компонент навигации, console.log не выводится снова. Почему?

И для чего это стоит, я использую стандарт navigation.navigate('ScreenName') в NavComponent до go от экрана к экрану.

Любые советы о том, как исправить предупреждение (и / или просто лучше спроектировать приложение), чтобы я мог иметь навигацию на каждой странице. Спасибо.

1 Ответ

0 голосов
/ 17 марта 2020

ваш вызов API приводит к предупреждению, в реагирующей / нативной экосистеме, когда компонент удаляется из дерева, разработчик должен отменить все подписки (прослушиватели событий) и асинхронные c задачи (извлечение данных из в Интернете), эти функции должны быть отменены разработчиком, так как реагирует / нативный не может сделать это за вас.

Чтобы справиться с этим в компоненте, основанном на классе, вам нужно ввести componentWillUnmount и удалить там подписки.

class MyClass extends Component {
   componentWillUnmount() {
     // remove listeners and cancel requests
    }

, но в современном компоненте ловушек вам необходимо вернуть функцию очистки , функцию, возвращаемую в useEffect, которая будет вызываться по реакции для отмены любых подписок, которые вы сделали, в вашем случае просто верните функцию очистки, которая должна удалить это предупреждение для вас


  const [mounted, setIsMounted] useState(false)
 useEffect(() => {
        // getPageData is a custom method I added to axios.
        setIsMounted(true)
        axios.getPageData('/api/url/here', (data) => {
            if(isMounted)
             setServerData(data);
        });

        return () => {
             setIsMounted(false)
         }
    }, []);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...