Установка контекста из дочернего элемента вызывает бесконечный цикл вызова

У меня есть приложение, использующее react-router-dom.

// App.js
function App() {
    return (
        <SiteContextProvider>
            <Switch>
                <Route path="/player/:slug"><PlayerPage /></Route>
                <Route default><NotFoundPage /></Route>
            </Switch>
        </SiteContextProvider>
        );
}

Дочерний компонент PlayerPage устанавливает для SiteContext значение параметра slug, переданного в URL-адресе.

// SiteContextProvider.js
export const SiteContext = React.createContext(null);

export function SiteContextProvider(props) {
    const [value, setValue] = useState(null);

    return <SiteContext.Provider value={{value, setValue}}>{props.children}</SiteContext.Provider>;
}
export function PlayerPage(props) {
    const { slug } = useParams();
    const { value, setValue } = useContext(SiteContext);
    setValue(slug);

    return <span>{value}</span>;
}

Проблема в том, что при загрузке PlayerPage он вызывает setValue, который устанавливает значение контекста, перезагружая PlayerPage. Это вызывает бесконечный цикл и мой код дает сбой. Как сделать так, чтобы PlayerPage устанавливал значение контекста только один раз?


person Amos    schedule 16.09.2020    source источник


Ответы (1)


Ваша проблема здесь:

export function PlayerPage(props) {
    const { slug } = useParams();
    const { value, setValue } = useContext(SiteContext);
    // Don't call setValue directly inside the function
    setValue(slug);

    return <span>{value}</span>;
}

Это приводит к изменению состояния контекста - ›повторная визуализация этого компонента, которая снова изменит состояние -› повторная визуализация этого компонента и т. Д.

вместо этого вы должны вызвать его внутри эффекта:

export function PlayerPage(props) {
    const { slug } = useParams();
    const { value, setValue } = useContext(SiteContext);

    React.useEffect(() => {
        setValue(slug);
    }, [slug, setValue]);

    return <span>{value}</span>;
}
person tudor.gergely    schedule 16.09.2020