В этой статье мы будем создавать коммутатор темы, используя стиливые компоненты, контекст API и, конечно же, реагировать.
Живой пример: https://codesandbox.io/s/react-theme-swticher-hbgjc
Репозиторий GitHub: https://github.com/holdmypotion/React-Theme-Swticher
Запустите следующие команды, чтобы инициировать приложение React.
npx create-react-app theme-switcher cd theme-switcher yarn add styled-components styled-normalize
Таким образом, у вас есть приложение React, работающее на стиле компонентов.
Теперь в папке SRC Создайте
- папка компонентов, а затем файл Mayout.js внутри.
- папка контекста, а затем файл GlobalContext.js внутри
- папка страниц, а затем файл home.js в пределах
- папка Styles, а затем файл Global Styles.js в качестве файла homestyles.js.
Конечная структура должна выглядеть примерно так.
Внутри файла GlobalContext.js вставьте приведенный ниже код.
//globalContext.js
import React, { useState } from "react";
export const GlobalContext = React.createContext({
currentTheme: "",
themeSwitchHandler: () => {},
});
const GlobalContextProvider = (props) => {
const [currentTheme, setCurrentTheme] = useState(
window.localStorage.getItem("theme") == null
? "light"
: window.localStorage.getItem("theme")
);
const themeSwitchHandler = (themeType) => {
setCurrentTheme(themeType);
};
return (
{props.children}
);
};
export default GlobalContextProvider;
Приведенный выше код создает контекст с функцией изменения состояния и состояния.
В конце концов, свойства, упомянутые в опоре Value, будут доступны для компонентов с использованием usecontext () крюка.
value={{
theme: currentTheme,
themeSwitchHandler: themeSwitchHandler,
}}
Используя контекст: вставьте код ниже в файл index.js.
// index.js import React from "react"; import ReactDOM from "react-dom"; import "./index.css"; import App from "./App"; import reportWebVitals from "./reportWebVitals"; import GlobalContextProvider from "./context/globalContext"; ReactDOM.render({/* Wrap the App component with the GlobalContextProvider created in the previous code snippet */} , document.getElementById("root") ); // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals();
Вставьте приведенный ниже код в файл “src/components/layout.js”.
// Layout.js
import React, { useContext } from "react";
import { createGlobalStyle, ThemeProvider } from "styled-components";
import { normalize } from "styled-normalize";
import { GlobalContext } from "../context/globalContext";
// 1.
const GlobalStyle = createGlobalStyle`
${normalize}
* {
text-decoration: none;
}
html {
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
font-size: 16px;
}
body {
font-family: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;;
background: ${(props) => props.theme.background};
}
`;
// 2.
const Layout = ({ children }) => {
const darkTheme = {
background: "#111827",
secondaryBackground: "#374151",
text: "#F9FAFB",
button: "#E5E7EB",
};
const lightTheme = {
background: "#F9FAFB",
secondaryBackground: "#E5E7EB",
text: "#111827",
button: "#374151",
};
// 3.
const currentTheme = useContext(GlobalContext);
// 4.
let theme;
switch (currentTheme.theme) {
case "dark":
theme = darkTheme;
break;
case "light":
theme = lightTheme;
break;
default:
theme = lightTheme;
}
return (
{children}
);
};
export default Layout;
Давай разберем это
- Постоянка Global Style определяет базовые стили, которые обычно определяются в файле index.css.
- Компонент макета имеет две константы, темные и легкие, и мы будем создавать кнопку переключения для переключения между ними. Используя ту же стратегию, вы можете создать столько тем, сколько хотите.
- Далее мы получаем текущую среду из GlobalContext.
- Оператор дела Switch Case заполняет переменную «тема», которая впоследствии передается в компонент Themeprovider, предоставленную стилизованными компонентами.
Мне нравится разделять свои стиливые компоненты на основе страниц. Поскольку некоторые стили распространены на страницах, я также создаю файл GlobalStyles.js для определения его.
// globalStyles.js
import styled, { css } from "styled-components";
export const Container = styled.div`
margin: 0 auto;
padding: 0 32px;
width: auto;
height: 100%;
${(props) =>
props.fluid &&
css`
padding: 0;
margin: 0;
max-width: 100%;
`}
`;
export const Flex = styled.div`
display: flex;
align-items: center;
${(props) =>
props.center &&
css`
justify-content: center;
`};
${(props) =>
props.column &&
css`
flex-direction: column;
`}
`;
СТАРИЧЕСКИЕ СТИЛЫ
// homestyles.js
import styled from "styled-components";
export const NavBar = styled.div`
background-color: ${(props) => props.theme.secondaryBackground};
padding: 20px 0;
`;
export const SwitchButton = styled.label`
position: relative;
display: inline-block;
width: 60px;
height: 34px;
input {
opacity: 0;
width: 0;
height: 0;
}
span {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: ${(props) => props.theme.button};
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 34px;
}
span:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: ${(props) => props.theme.secondaryBackground};
-webkit-transition: 0.4s;
transition: 0.4s;
border-radius: 50%;
}
input:checked + span {
background-color: ${(props) => props.theme.button};
}
input:focus + span {
box-shadow: 0 0 1px #2196f3;
}
input:checked + span:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
`;
export const Body = styled.div`
padding: 3em 5em;
`;
export const Heading = styled.div`
font-size: 5em;
font-weight: 800;
color: ${(props) => props.theme.text};
`;
export const SubPara = styled.p`
font-size: 1.5em;
color: ${(props) => props.theme.text};
`;
export const Para = styled.p`
font-size: 1.2em;
line-height: 1.5;
color: ${(props) => props.theme.text};
width: 80%;
`;
export const Content = styled.div`
padding: 10em 0;
`;
Теперь, когда мы закончили создать наши маленькие компоненты в стиле. Пришло время использовать их для создания последней страницы
Вставьте приведенный ниже код в файл “src/components/home.js”
// Home.js
import React, { useContext, useEffect } from "react";
import { GlobalContext } from "../context/globalContext";
import Layout from "../components/Layout";
import { Container, Flex } from "../styles/globalStyles";
import {
NavBar,
SwitchButton,
Body,
Heading,
SubPara,
Para,
Content,
} from "../styles/homeStyles";
const Home = () => {
// 1.
const { theme, themeSwitchHandler } = useContext(GlobalContext);
useEffect(() => {
window.localStorage.setItem("theme", theme);
}, [theme]);
return (
{/* 2. */}
themeSwitchHandler(theme === "dark" ? "light" : "dark")
}
/>
Hello
What's up! Toggle the switch above to change the theme
Article
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
Reprehenderit quis ipsa, sunt, consectetur voluptate dolores
pariatur nisi distinctio iusto vero iure officia. Vero sunt,
ducimus sit eveniet dolor impedit itaque voluptate ipsam!
Omnis totam, beatae dicta fugit praesentium fugiat dolores
laborum, officiis, labore aperiam tempore! Debitis, provident!
Rem, exercitationem enim?
);
};
export default Home;
Давайте разберем это:
- Мы получаем наш контекст из GlobalContext, используя usecontext () крюк.
- Опора «OnChange» кнопки переключения переключает тему между темным и светом. (Лучшим способом было бы создать отдельную кнопку, чтобы вызвать различные темы, так как у нас уже есть оператор по переключению, чтобы выбрать тему в файле Mayout.js.)
Наконец, импортируйте этот компонент в файл app.js
import Home from "./pages/Home";
function App() {
return (
);
}
export default App;
Этот метод использования компонента Themeprovider для установки тем не ограничивается только цветами, так как очевидно, что вы можете определить любой вид стилей, хранить их в постоянную, а затем передать его в качестве темы.
Будьте креативны, подумайте о некоторых вариантах использования, когда вы можете пройти разные маржи, заполнения или, возможно, ширину. Вы также можете пройти разные шрифты, возможно, создать сайт, такой как https://www.happyhues.co/ Это очень весело, так что наверняка попробуйте.
Я хотел бы услышать ваши взгляды. Обязательно прокомментируйте ниже!
Оригинал: “https://dev.to/holdmypotion/react-theme-switcher-5d2a”