React - 如何使用上下文从对象中应用多个值

Posted

技术标签:

【中文标题】React - 如何使用上下文从对象中应用多个值【英文标题】:React - How to apply multiple values from an object using context 【发布时间】:2021-04-29 20:52:15 【问题描述】:

为此,我在我的项目中使用了一个颜色主题,我使用了一个 React 上下文来传递几个组件中的值,一切对我来说都很好,直到我决定在对象中添加另一个属性以便将不同的颜色应用于不同的组件,例如将绿色作为值的ThemeBackground 属性将应用于RoutesPage 组件,而将橙色应用于SideBar 组件的侧属性。问题是我无法为SideBar 组件应用side 属性,我尝试了几个选项,但我现在没有成功,我将在图片中更详细地向您展示所有内容,以便您清楚地了解问题然后我会给你代码

请注意 ThemesBackground 属性已成功应用于内容,但问题是我想在我为边栏导入 ThemeBackground 属性时将 side 属性应用到边栏,所以我的边栏应用红色颜色,但我认为您已经理解了短属性ThemeBackground 应该应用于内容和side 属性到侧边栏的问题

LessonThemes.jsx

import React,  useState, useEffect, createContext  from "react";
import SideBar from "./SideBar";
import RoutesPage from "../pages/Routes";

export const CounterContext = createContext(["color"]);


export default function LessonThemes(props) 
    const [BackgroundTheme, SetBackgroundTheme] = useState(localStorage.getItem("color"));

    const [themes, setThemes] = useState([
         name: "G", ThemeBackground: "maroon", side: "orange" ,
         name: "R", ThemeBackground: "red", side: "aqua"  ,
         name: "B", ThemeBackground: "blue", side: "pink"  ,
    ])

    useEffect(() => 
        localStorage.setItem("color", BackgroundTheme);
    )

    const SideBarPageContent = (SideBarPageContentBackground) => 
        localStorage.setItem('color', SideBarPageContentBackground);
        SetBackgroundTheme(SideBarPageContentBackground);
    

    const list = themes.map((theme, index) => 
        return (
            <label key=index>
                <input
                    onChange=() => SideBarPageContent(theme.ThemeBackground)
                    type="radio"
                    name="background"
                />theme.name</label>
        );
    )

    return (
        <CounterContext.Provider value=[BackgroundTheme, SetBackgroundTheme]>
            <SideBar list=list ...props />
            <RoutesPage path=props.match />
        </CounterContext.Provider>
    );

SideBar.jsx

import React from 'react';
import CounterContext from "./LessonThemes";
import SideBarMenu from "./SideBarMenu";
import '../css/Sidebar.css'

export default function SideBar(props) 
    const [BackgroundTheme, SetBackgroundTheme] = React.useContext(CounterContext);
    return (
        <div className="wrappers">
            <nav id="sidebar" className="sidebar-wrapper modal">
                <div style=background: BackgroundTheme className="sidebar-page-content">
                    <div className="sidebar-brand">
                        <div className="sidebar-brand-container">
                            <div>
                                props.list
                            </div>
                            <div>
                                <span href="#">Theme</span>
                            </div>
                        </div>
                    </div>

                    <div className="sidebar-menu">
                        <SideBarMenu path=props.match.path/>
                    </div>

                    ...
                </div>
            </nav>
        </div>
    );

不知道对你有用没

RoutesPage.jsx

import React from "react";
import Route, Switch from "react-router-dom";
import '../css/Sidebar.css'
import CounterContext from "../components/LessonThemes";

function RoutesPage(props) 
    const path = props.path;

    const routes = [
        
            path: `$path`,
            exact: true,
            component: () => <h2>Home</h2>
        ,
        
            path: `$path/Calendar`,
            component: () => <h2>Test123</h2>
        ,
        
            path: `$path/Guardian`,
            component: () => <h2>Shoelaces</h2>
        
    ];
    const [BackgroundTheme, SetBackgroundTheme] = React.useContext(CounterContext);

    return (
        <>
            <main style=background: BackgroundTheme className="page-content">
                <div className="page-container">
                    <h2>Pro Sidebar</h2>
                    <hr/>
                    <div className="tabs">
                        <Switch>
                            routes.map((route, index) => (
                                <Route
                                    key=index
                                    path=route.path
                                    exact=route.exact
                                    component=route.component
                                />
                            ))
                        </Switch>
                    </div>
                </div>
            </main>
        </>
    );


export default RoutesPage;

【问题讨论】:

【参考方案1】:

是否可能在 SideBar.jsx 中,div 样式需要设置为 BackgroundTheme 而不是 SideBarBackgroundTheme?它也不会传入对象,因此您仍然需要键入特定颜色的键吗?喜欢 BackgroundTheme.side?​​p>

【讨论】:

【参考方案2】:

问题是side 属性永远不会存储到上下文的value 中。您的上下文值仍然只是 string。存在的完整主题对象只是LessonThemes 组件的本地状态。

inputonChange 处理程序中,您调用SideBarPageContent,后者又调用SetBackgroundTheme,这会更新您传递给上下文提供程序的BackgroundTheme 属性。您传递给此函数调用的参数是theme.ThemeBackground——它只是背景颜色,而不是整个对象。

您可能希望重构代码,以便上下文包含整个对象。

SideBar 组件中,不清楚您认为变量SideBarBackgroundTheme 来自何处,但该变量不存在。

【讨论】:

在我问这个问题之前这是我的错,我尝试了几个选项并忘记更改 SideBarBackgroundTheme 而不是这个现在应该是 BackgroundTheme 我当然编辑了我的问题但是问题没有解决 你明白这个问题吗?您的上下文只是一种颜色,而不是具有多种颜色的对象? 我能够解决这个问题,我会尽快回答我的问题【参考方案3】:

LessonThemes.jsx

import React, useState, useEffect, createContext from "react";
import SideBar from "./SideBar";
import RoutesPage from "../pages/Routes";

export const CounterContext = createContext([]);


export default function LessonThemes(props) 
    const [SideBarTheme, SetSideBarTheme] = useState(localStorage.getItem("SideBarKey"));
    const [PageContentTheme, SetPageContentTheme] = useState(localStorage.getItem("PageContentKey"));

    const [themes, setThemes] = useState([
        
            name: "G",
            SideBar: "maroon",
            PageContent: "blue",
        ,
        
            name: "R",
            SideBar: "gray",
            PageContent: "green",
        ,
    ])

    useEffect(() => 
        localStorage.setItem("SideBarKey", SideBarTheme, "PageContentKey", PageContentTheme);
    )

    const SideBarPageContent = (PageContent, SideBar) => 
        localStorage.setItem('PageContentKey', PageContent, 'SideBarKey', SideBar);
        SetPageContentTheme(PageContent);
        SetSideBarTheme(SideBar);
    

    const list = themes.map((theme, index) => 
        return (
            <label key=index>
                <input
                    onChange=() => SideBarPageContent(theme.PageContent, theme.SideBar)
                    type="radio"
                    name="background"
                />theme.name</label>
        );
    )

    return (
        <CounterContext.Provider value=
            SideBarValue: [SideBarTheme, SetSideBarTheme],
            PageContentValue: [PageContentTheme, SetPageContentTheme]
        >
            <SideBar list=list ...props />
            <RoutesPage path=props.match/>
        </CounterContext.Provider>
    );

SideBar.jsx

export default function SideBar(props) 

    const  SideBarValue  = React.useContext(CounterContext);
    const [SideBarTheme, SetSideBarTheme] = SideBarValue;

    return (
        <div className="wrappers">
            <nav id="sidebar" className="sidebar-wrapper modal">
                <div style=background: SideBarTheme className="sidebar-page-content">
                    <div className="sidebar-brand">
                        <div className="sidebar-brand-container">
                            <div>
                                props.list
                            </div>
                            <div>
                                <span href="#">Theme</span>
                            </div>
                        </div>
...

RoutesPage.jsx

import React from "react";
import Route, Switch from "react-router-dom";
import '../css/Sidebar.css'
import CounterContext from "../components/LessonThemes";

function RoutesPage(props) 
    const path = props.path;

    const routes = [
        
            path: `$path`,
            exact: true,
            component: () => <h2>Home</h2>
        ,
        
            path: `$path/Calendar`,
            component: () => <h2>Test123</h2>
        ,
        
            path: `$path/Guardian`,
            component: () => <h2>Shoelaces</h2>
        
    ];

    const  PageContentValue  = React.useContext(CounterContext);
    const [PageContentTheme, SetPageContentTheme] = PageContentValue;

    return (
        <>
            <main style=background: PageContentTheme className="page-content">
...

【讨论】:

以上是关于React - 如何使用上下文从对象中应用多个值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 React Context API 挂钩中访问多个上下文的调度方法?

React - 如何获取上下文中钩子的值

如何使用 React Context API 跨多个 Routes 拥有状态?

Core Data 使用多个上下文中的新对象从后台线程订购一对多关系保存

如何在 React v16.6 的新 CONTEXT API 中获取多个静态上下文

在 React 中使用 useContext 和 useReducer 创建新的键值对