реагировать на крючки, избегать повторного рендеринга и сохранять требуемый уровень - PullRequest
0 голосов
/ 18 апреля 2020

Я что-то упустил с useEffect, useCallback и deps.

У меня есть один контекст и один компонент. Мой компонент загружает все нужные мне данные с помощью fetch () и устанавливает логическое значение true в контексте, чтобы показать счетчик. Я использую контекст в другом компоненте, когда мне это нужно.

const LoadingApp = ({children}) => {
    const loadingContext = useContext(LoadingContext);

    const fetchMyData = useCallback(() => {
        loadingContext.setLoading(true);
    }, [loadingContext]);


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

    return (
        <React.Fragment>
            {children}
        </React.Fragment>
    );
};


const LoadingProvider = ({children}) => {
    const [loading, setLoading] = useState(false);

    const setLoading = useCallback((isLoading) => {
        setLoading(loading + (isLoading ? 1: -1));
    }, [setLoading, loading]);

    const isLoading = useCallback(() => {
        return loading > 0;
    }, [loading]);

    return (
        <LoadingContext.Provider value={{setLoading, isLoading}}>
            {children}
        </LoadingContext.Provider>
    )
}

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

Как я могу вызвать функцию в контексте в useEffect или useCallback без повторного рендеринга всего?

Ответы [ 2 ]

0 голосов
/ 18 апреля 2020

Контекст всегда изменяется при изменении значения loading. Измените зависимости useEffect, чтобы они зависели только от setLoading, который основан на useCallback (установщик useState также не изменяется) и останется фиксированным.

const { setLoading } = useContext(LoadingContext);

const fetchMyData = useCallback(() => {
  setLoading(true);
}, [setLoading]);

Вы на самом деле useCallback не нужен, поскольку он делает то же самое, что и оригинальный setLoading. Вы можете безопасно удалить это:

const setLoading = useCallback((isLoading) => {
  setLoading(isLoading);
}, [loading]);
0 голосов
/ 18 апреля 2020

Если вы звоните setLoading, то вы всегда будете запускать повторный рендеринг, который вам нужен.

У вас может быть пустой deps, что означает, что эффект будет запущен только один раз.

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