为什么当我尝试用另一个处理状态的组件包装我的主组件时会出现错误?

huangapple go评论128阅读模式
英文:

Why am I getting error when trying to wrap my main component with another component that handles state?

问题

我有一个名为 Settings 的组件,负责切换明亮/暗黑模式。然而,在导航到另一个组件后,暗黑模式的状态不会保留(会回到明亮模式)。

我试图做的是在所有组件之间共享状态,而无需使用额外的库,通过使用 React Context 解决方案。

下面是我收到的错误,我不确定如何修复它。我已经尝试了很多种方法。任何建议将不胜感激。

警告:一个上下文消费者被渲染为多个子元素,或者一个不是函数的子元素。上下文消费者期望一个单一的函数子元素。如果您传递了一个函数,请确保其周围没有尾随或前导空白。

App.js

const App = () => {
    return (
        <>
            <DarkModeContext.Consumer>
                <Router>
                    <Switch>
                        <Route exact path="/" component={Home} />
                        <ProtectedRoute path="/settings" component={Settings} />
                    </Switch>
                </Router>
            </DarkModeContext.Consumer>
        </>
    );
}

const container = document.getElementById('example');
const root = createRoot(container);
root.render(<UserProvider><App/></UserProvider>);

Settings.js

import React, { useContext, useEffect } from 'react';
import Switch from '@mui/material/Switch';
import { FormControlLabel, Grid } from '@mui/material';
import { DarkModeContext } from "../../utilities/DarkModeContext";

const Settings = () => {
    const { darkModeChecked, toggleDarkMode } = useContext(DarkModeContext);

    useEffect(() => {
        document.body.style.backgroundColor = darkModeChecked ? 'black' : 'white';
    }, [darkModeChecked]);

    return (
        <Grid container direction="column" alignItems="center" justifyContent="center" spacing={2}>
            <Grid item>
                <FormControlLabel
                    control={<Switch checked={darkModeChecked} onChange={toggleDarkMode} />}
                    label="Text to the top"
                    labelPlacement="top"
                />
            </Grid>
        </Grid>
    );
};

export default Settings;

DarkModeContext.js

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

export const DarkModeContext = createContext();

export const DarkModeProvider = ({ children }) => {
    const [darkModeChecked, setDarkModeChecked] = useState(true);

    const toggleDarkMode = () => {
        setDarkModeChecked((prev) => !prev);
    };

    return (
        <DarkModeContext.Provider value={{ darkModeChecked, toggleDarkMode }}>
            {children}
        </DarkModeContext.Provider>
    );
};
英文:

I have a Settings component which handles toggling light/dark mode. However, upon navigating to another component, the state of the dark mode doesn't persist (it goes back to light mode).

What I'm trying to do is share the state across all components without the need for additional libraries by using the state management solution React Context.

This is the error I'm getting below and I'm not sure how to fix it. I've tried so many ways. Any suggestions would be appreciated.

Warning: A context consumer was rendered with multiple children, or a child that isn&#39;t a function. A context consumer expects a single child that is a function. If you did pass a function, make sure there is no trailing or leading whitespace around it.

App.js

const App = () =&gt; {
    return (
        &lt;&gt;
         &lt;DarkModeContext.Consumer&gt;
            &lt;Router&gt;
                &lt;Switch&gt;
                    &lt;Route exact path=&quot;/&quot; component={Home} /&gt;
                    &lt;ProtectedRoute path=&quot;/settings&quot; component={Settings} /&gt;
                &lt;/Switch&gt;
            &lt;/Router&gt;
         &lt;/DarkModeContext.Consumer&gt;
        &lt;/&gt;
    );
}

const container = document.getElementById(&#39;example&#39;);
const root = createRoot(container);
root.render(&lt;UserProvider&gt;&lt;App/&gt;&lt;/UserProvider&gt;);

Settings.js

import React, { useContext, useEffect } from &#39;react&#39;;
import Switch from &#39;@mui/material/Switch&#39;;
import { FormControlLabel, Grid } from &#39;@mui/material&#39;;
import {DarkModeContext} from &quot;../../utilities/DarkModeContext&quot;;

const Settings = () =&gt; {
    const { darkModeChecked, toggleDarkMode } = useContext(DarkModeContext);

    useEffect(() =&gt; {
        document.body.style.backgroundColor = darkModeChecked ? &#39;black&#39; : &#39;white&#39;;
    }, [darkModeChecked]);

    return (
        &lt;Grid container direction=&quot;column&quot; alignItems=&quot;center&quot; justifyContent=&quot;center&quot; spacing={2}&gt;
            &lt;Grid item&gt;
                &lt;FormControlLabel
                    control={&lt;Switch checked={darkModeChecked} onChange={toggleDarkMode} /&gt;}
                    label=&quot;Text to the top&quot;
                    labelPlacement=&quot;top&quot;
                /&gt;
            &lt;/Grid&gt;
        &lt;/Grid&gt;
    );
};

export default Settings;

DarkModeContext.js

import React, { createContext, useState } from &#39;react&#39;;

export const DarkModeContext = createContext();

export const DarkModeProvider = ({ children }) =&gt; {
    const [darkModeChecked, setDarkModeChecked] = useState(true);

    const toggleDarkMode = () =&gt; {
        setDarkModeChecked((prev) =&gt; !prev);
    };

    return (
        &lt;DarkModeContext.Provider value={{ darkModeChecked, toggleDarkMode }}&gt;
            {children}
        &lt;/DarkModeContext.Provider&gt;
    );
};

答案1

得分: 1

这不是正确使用 Context.Consumer 的方式。警告告诉您问题所在。它期望一个返回 React 元素的函数。

<Context.Consumer>{(thingsFromContextValue) => <Component />}</Context.Consumer>

您目前的用法没有意义。Consumer 用于提供返回值,如果您不使用该值,就不需要使用 Consumer。

另外,我看不到您在哪里使用了您的 DarkModeProvider。它必须包裹那些使用该上下文的部分。

英文:

This is not the right way of using Context.Consumer. The warning tells you what the problem is. It expects function that return ReactElement.

&lt;Context.Consumer&gt;{(thingsFromContextValue) =&gt; &lt;Component /&gt;}&lt;/Context.Consumer&gt;

The way you using it does not make sense. It is there to give the return value, if you are not using that value, no need to use the Consumer.

Also I don't see where you use your DarkModeProvider. It has to wrap those that use that context

huangapple
  • 本文由 发表于 2023年5月29日 22:12:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76358073.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定