37
loading...
This website collects cookies to deliver better user experience
I just created a new folder sun-moon
and copied everything from the previous post (react-from-scratch
) except node_modules
and did a fresh npm i
.
npm i css-loader mini-css-extract-plugin -D
css
in our js
file, as shown below:// in App.js file
import "./App.css";
App.css
in src
folder and import it in App.js
.const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve(__dirname, "./public"),
filename: "bundle.js",
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: "babel-loader",
},
{
test: /(\.scss|\.css)$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
plugins: [new HtmlWebpackPlugin({ template: "./public/index.html" }), new MiniCssExtractPlugin()],
};
This is basically going to contain Sun/Moon
svg
as react component.
React Component
from SVG
but we can also use this playground
which will just convert the SVG
to react component for us: React SVGR---sun-moon
|--node_modules
|--...
|--src
|--App.js
|--App.css
|--index.js
|--Sun.js
|--Moon.js
DarkContext.js
in src
folder, with this content:
import { createContext } from "react";
export const DarkContext = createContext(false);
DarkContext
using createContext method from React library.DarkContext
has the default theme value as false
.App
with DarkContext.Provider
and specify the initial value.DarkContext
.Sun
and Moon
Component needs to know if current context is Dark
or Light
(not-dark).Note: We could have passed the value of theme using props, and that would also be okay, but let's try to get a feel of react's context api.
App.js
will look like this:import React, { useState } from "react";
import { DarkContext } from "./DarkContext";
import "./App.css";
const App = () => {
const [isDark, setIsDark] = useState(false);
return (
<DarkContext.Provider value={isDark ? true : false}>
<div className="instruction">Click On Sun/Moon 👇</div>
<div className={`app${isDark ? " dark" : ""}`}>
Hello World
</div>
</DarkContext.Provider>
);
};
export default App;
App
is also maintaining
an internal state isDark
, which helps to update our context value:<DarkContext.Provider value={isDark ? true : false}>
...
</DarkContext.Provider>
import React, { useContext } from "react";
import Moon from "./Moon";
import Sun from "./Sun";
function ThemeIcon(props) {
const { onClick } = props;
return (
<div className="theme-icon" onClick={onClick}>
<Sun></Sun>
<Moon></Moon>
</div>
);
}
export default ThemeIcon;
Sun
and Moon
component, it also needs to have an onClick
handler which will change the value of isDark
from App's
internal state and that has to be passed down from App
component.import React, { useState } from "react";
import { DarkContext } from "./DarkContext";
import ThemeIcon from "./ThemeIcon";
import "./App.css";
const App = () => {
const [isDark, setIsDark] = useState(false);
return (
<DarkContext.Provider value={isDark ? true : false}>
<div className={`app${isDark ? " dark" : ""}`}>
<ThemeIcon onClick={() => setIsDark(!isDark)}></ThemeIcon>
</div>
</DarkContext.Provider>
);
};
export default App;
<div className={`app${isDark ? " dark" : ""}`}>
css
:.app {
width: 100vw;
height: 100vh;
...
}
.dark {
...
}
div.app
is going to be full width
and full height
. And whenever the value of isDark
is true
i am going to add css class dark
as well. useContext
DarkContext
.useContext
is the current value of the context (true/false
).useContext
to get the current value of the context in Sun/Moon
component.const isDark = useContext(DarkContext);
Sun
and Moon
will now look like this:import React, { useContext } from "react";
import PropTypes from "prop-types";
import { DarkContext } from "./DarkContext";
function Sun() {
// Things to notice here:
const isDark = useContext(DarkContext);
return (
<svg
version="1.1"
id="Capa_1"
x="0px"
y="0px"
viewBox="0 0 457.32 457.32"
// Things to notice here:
className={`sun ${isDark ? " sun-dark" : ""}`}
>
...
</svg>
);
}
export default Sun;
Moon
component as well.npm run start:dev
http://localhost:8080/
.css
part, but if we are able to understand how sun
is disappearing and how moon
comes up, and how moon
disappears and sun
comes up, then we can say we understood it completely.css
code here or in github
(link shared at the end of this post) and try to understand what is going on, but instead let's look at these two screenshots, I believe that should be enough to understand the logic, rest all is just writing code for that logic.IconContainer
(in terms or our code it is ThemeIcon
component, that we created above), that is holding Sun
icon/component, the opacity of sun is 1
and there we also see Moon
but it's not going to be visible because it's opacity is 0
{opacity: 0}
, when i click on IconContainer
our Sun
is going to be invisible by making its opacity as Zero(0)
(by adding extra class sun-dark
) and moon's opacity will become One(1)
(by adding extra class, moon-dark
to the moon svg, based on the value of isDark
), we can have another look at Sun/Moon
component and see how css
classes
are getting added.DarkContext
's value is going to be true.Sun/Moon
is going to know that change, through context, based on that they are going to act.Sun
is going to attach sun-dark
class to it's SVG
, which will make it invisible (opacity: 0
)Moon
is going to attach moon-dark
class as well to it's SVG
, which will make it visible (opacity: 1
)transitions
and transformation
that I have added to make it more interesting, but not to worry, if we are able to understand the logic above, things will be easy.