首页 > 解决方案 > 如何在 react 和 styled-components 中使用 json 文件切换主题?

问题描述

我已经为此工作了好几天,但我仍然被困住了,所以我真的可以使用一些帮助。
我已经尝试了一些我在网上找到的东西,并且一些东西有效。但它们要么非常复杂和繁琐,要么在某种程度上不是这样,因此我可以重新排列它们以在我的项目中按照我的意愿工作。

我有一些要求,我希望遵循:

目前,JSON 文件加载到 localStorage,按钮获取它们的字体和颜色,程序注册按下哪个按钮。

目标是按下一个主题按钮,主题背景和主页都会相应地更改颜色和字体。

这是重要的部分!

import { useState, useEffect } from 'react';
import styled from 'styled-components';
import data from './ThemeData.json';
import _ from 'lodash';
import WebFont from 'webfontloader';
import { ThemeProvider } from "styled-components";

const ThemeContainer = styled.div`
    position: absolute;
    height: 15rem;
    width: 100%;
    max-width: 80rem;
    top: 0;
    left: 50%;
    transform: translateX(-50%);
    background: #ededed;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    box-shadow: 0 .2rem .4rem rgba(0,0,0,.3);
`

const ThemeCard = styled.li`
    height: 6rem;
    width: 12rem;
    border: .1rem solid #222;
    display: flex;
    justify-content: center;
    align-items: center;
    margin: 0 1rem;
    border-radius: .5rem;
    background: red;
`

const ThemeButton = styled.button`
    height: 4rem;
    width: 10rem;
    margin: 0 1rem;
    display: flex;
    justify-content: center;
    align-items: center;
    border: .1rem solid #333;
    border-radius: .4rem;
    outline: none;
    box-shadow: 0 .2rem .4rem rgba(0,0,0, .6);
    transition: .2s ease-out;
    &:hover{
        box-shadow: none;
    }
`

const ThemeSection = () => {
    const [theme, setTheme] = useState(data, () => {
        const localData = localStorage.getItem('themes');
        return JSON.parse(localData)
    });

    useEffect(() => {
        localStorage.setItem('themes', JSON.stringify(theme));
        setTheme(theme)
    }, [theme]);

    function ThemeSwitcher(selectedTheme) {
        console.log(selectedTheme);
        setTheme(theme)
    }

    const getFonts = () => {
        const allFonts = _.values(_.mapValues(data, 'font'));
        return allFonts;
    }

    useEffect(() => {
        WebFont.load({
            google: {
                families: getFonts()
            }
        });
    });

    return (
        <>

            <ThemeContainer>
                {theme.map(theme => (
                    <ThemeCard theme={theme[theme]} key={theme.id}
                        style={{
                            background: `${theme.themeCard}`
                        }}>
                        <ThemeButton onClick={() => { ThemeSwitcher(theme) }}
                            style={{
                                background: `${theme.background}`,
                                color: `${theme.text}`,
                                fontFamily: `${theme.font}`
                            }}
                        >{theme.title}</ThemeButton>
                    </ThemeCard>
                ))
                }
            </ThemeContainer>
        </>
    )
}

export default ThemeSection

全球风格:

import { createGlobalStyle } from 'styled-components';

export const GlobalStyle = createGlobalStyle`
  *,
  ::after,
  ::before {
    margin: 0;
    padding: 0;
    box-sizing: inherit;
  }
  
  html {
    font-size: 62.5%;
  }
  
  body {
    box-sizing: border-box;
    font-family: 'montserrat', sans-serif;
  }
  
  a {
    text-decoration: none;
  }
  
  ul, li {
    list-style: none;
  }
`;

应用程序.js

import { GlobalStyle } from './globalStyle'
import MainPage from './components/MainPage'

function App() {
  return (
    <>
      <GlobalStyle />
      <MainPage />
    </>
  );
}

export default App;

主页:

import { MainSection, MainBox, MainText } from './MainPage.elements'
import ThemeSection from './theme/ThemeSection'

const MainPage = () => {
    return (
        <>
            <MainSection>
                <ThemeSection />
                <MainBox>
                    <MainText>just some random text</MainText>
                </MainBox>
            </MainSection>
        </>
    )
}

export default MainPage

造型:

import styled from 'styled-components';

export const MainSection = styled.section`
  height: 100vh;
  width: 100%;
  max-width: 80rem;
  margin: 0 auto;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #f4c9b7;
`;

export const MainBox = styled.ul`
  height: 50%;
  width: 100%;
  background: #f4dfd6;
  display: flex;
  justify-content: center;
  align-items: center;
`;
export const MainText = styled.h5`
  text-align: center;
  color: #333;
  font-size: clamp(3rem, 4vw, 5rem);
  text-transform: capitalize;
  padding: 0 3rem;
`;

JSON 文件:

[
    {
        "id": "001",
        "title": "light",
        "sectionBackground": "#ffffff",
        "themeCard": "#ffffff",
        "background": "#ededed",
        "text": "#333",
        "font": "Tino"
    },
    {
        "id": "002",
        "title": "dark",
        "sectionBackground": "#333333",
        "themeCard": "#666666",
        "background": "#111111",
        "text": "#f1f1f1",
        "font": "Lato"
    },
    {
        "id": "003",
        "title": "purple",
        "sectionBackground": "#d0b7f4",
        "themeCard": "#d0b7f4",
        "background": "#7852ae",
        "text": "#999",
        "font": "Oswald"
    }
]

我试图用 stackblitz 来解决这个问题,但恐怕也没有运气。

非常感谢!

标签: jsonreactjslocal-storagethemesstyled-components

解决方案


推荐阅读