React native typescript: функции usecontext не запускаются изнутри дочернего компонента

#reactjs #typescript #react-native #use-context

#reactjs #typescript #react-native #использование-context

Вопрос:

У меня возникает проблема, когда я пытаюсь использовать функции из контекста внутри дочернего компонента в приложении React native для Android.

Ниже приведен мой код для контекста и компонента формы, в котором я его использую (сокращено для краткости).

Объект «isFormOpen» может быть прочитан без проблем изнутри любых дочерних элементов, которые завернуты в провайдере, но когда я пытаюсь вызвать функцию «toggleForm» из того же дочернего компонента, он ничего не делает, ошибок консоли тоже нет.

У меня есть другой контекст, который идентичен по структуре и синтаксису, за исключением имен переменных и функций и т.д., и это работает отлично, поэтому я немного смущен тем, почему это не работает. Я удалил другой контекст, думая, что может быть какой-то конфликт, но не решил его.

AccountContext.tsx

 import React, { FC, createContext, useContext, useState } from 'react';

interface AccountContextType {
    isFormOpen: boolean,
    toggleForm: (toggle: boolean) => void
};

export const AccountContext = createContext<AccountContextType>({
    isFormOpen: false,
    toggleForm: () => null
});

export const AccountContextProvider: FC = props => {
    const [formOpen, setFormOpen] = useState<boolean>(false);

    const toggleForm = (toggle: boolean) => {
        setFormOpen(toggle);
    }

    const value: AccountContextType = {
        isFormOpen: formOpen,
        toggleForm
    }

    return (
        <AccountContext.Provider value={value}>
            {props.children}
        </AccountContext.Provider>
    )
}

export const useAccountContext = () => useContext(AccountContext);
 

TrackUploadForm.js

 import React from 'react';
import { SafeAreaView } from 'react-native';
import { Button } from 'react-native-paper';

import { useAccountContext } from '../contexts/AccountContext';
import { AccountContextProvider } from '../contexts/AccountContext';

const TrackUploadForm = () => {
    const accountContext = useAccountContext();

    return (
        <AccountContextProvider>
            <SafeAreaView>
                <Button onPress={() => accountContext.toggleForm(false)} mode='outlined'>Cancel</Button>
            </SafeAreaView>
        </AccountContextProvider>
    )
};

export default TrackUploadForm;
 

Ответ №1:

  1. useAccountContext вызывается вне поставщика
 export default function App() {
  return (
    <AccountContextProvider>
      <Content />
    </AccountContextProvider>
  );
}

const Content = () => {
  const accountContext = useAccountContext();
  return (
    <div className="App">
      <h1>{accountContext.isFormOpen ? "true" : "false"}</h1>
      <Button onPress={() => accountContext.toggleForm(false)} mode='outlined'>Cancel</Button>
    </div>
  );
};
 
  1. accountContext.toggleForm(false) <— всегда false, измените его на accountContext.toggleForm(!accountContext.isFormOpen)

Вместе мы имеем https://codesandbox.io/s/cranky-panini-yo129

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

1. Ого, это сработало. Причина, по которой я не думал, что это произойдет, заключается в том, что я переместил оболочку вверх по дереву, но не так далеко, как обертывание всего приложения. У меня сложилось впечатление, что вы можете обернуть любой компонент, который вы хотите, и все его дочерние элементы могут использовать контекст, и смысл этого в том, чтобы разрешить только определенным компонентам использовать контекст. Спасибо.