How to create multi-items slider in React? - reactjs

I created a multi-items carousel and it's fetching all images from the database but only displaying 3 images. I need this carousel to display all images from the database when one click on side arrows. How can I make it work as "https://react-multi-carousel.now.sh/" this carousel? Can you help me with my custom carousel?
.home__wrapper {
.categoryslider__wrapper {
display: flex;
width: 100%;
margin-top: 15px;
visibility: visible;
opacity: 1;
transition: visibility 0s, opacity 0.05s, height 0.05s linear;
height: auto;
.category {
position: relative;
height: 14vh;
margin-bottom: 1em;
cursor: pointer;
& >img {
height: 100%;
width: 100%;
object-fit: cover;
}
p {
position: absolute;
top: 0.2em;
left: 1em;
color: rgb(255, 255, 255);
font-size: 2vh;
font-weight: 900;
letter-spacing: 0.5px;
line-height: 24px;
width: 80%;
text-align: left;
}
}
}
}
import React from 'react'
import {withRouter} from 'react-router'
import './index.scss'
import {times} from 'lodash'
import Carousel from 'react-bootstrap/Carousel'
import {Col} from 'react-bootstrap';
import {API} from '../../../constants';
class CategorySlider extends React.Component {
render() {
let {stores} = this.props;
return (
<>
<Carousel className='categoryslider__wrapper'>
{times(4, (index) => {
return (
<Carousel.Item key={index}>
{stores && stores.length && stores.map(store => {
if (store.featured_products.length){
return store.featured_products[0].image_url;
}
return stores[0].name;
}).filter(image=>image!==undefined).map((image_link, i )=> {
return (
<Col key={image_link + "" + i} className="col-4 category" >
<img src={API.files.detail.replace('/files/:fileUUID/', image_link)} alt=""></img>
<p>{stores[i].name}</p>
</Col>
)
})}
</Carousel.Item >
)
})}
</Carousel>
</>
);
}
}
export default withRouter(CategorySlider);

Related

REACT + TypeScript Accordion transition doesn't works

Sup guys i have a problem, i would like to do an animated accordion, it should to have a transition animated when it opens and collapse, and in icon switching
I'm creating by myself an accordion in react + typescript but this transition doesnt works and idk why, code below:
This my index.tsx
import { useState } from "react";
import { AccordionButton, AccordionContent, Wrapper } from "./styles";
import { AccordionProps } from "./interfaces";
import { BsChevronDown, BsChevronUp } from "react-icons/bs";
export default function Accordion({ title, text }: AccordionProps) {
const [isOpen, setIsOpen] = useState(false);
const handleClick = () => {
setIsOpen(!isOpen);
returnIcon();
};
const returnIcon = () => {
return isOpen ? <BsChevronUp /> : <BsChevronDown />;
};
return (
<Wrapper>
<AccordionButton onClick={handleClick}>
{title} {returnIcon()}
</AccordionButton>
<AccordionContent isOpen={isOpen}>
<p>{text}</p>
</AccordionContent>
</Wrapper>
);
}
and this is my styled component below:
import styled from "styled-components";
import { AccordionContentProps } from "./interfaces";
export const AccordionButton = styled.button`
background-color: #606582;
color: #ffffff;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.6s;
&:hover {
background-color: #60658295;
}
> svg {
float: right;
}
`;
export const AccordionContent = styled.div<AccordionContentProps>`
display: ${(props) => (props.isOpen === false ? "none" : "block")};
padding: 0 18px;
background-color: white;
overflow: hidden;
`;
export const Content = styled.div`
padding: 10px 0px;
flex-wrap: wrap;
max-width: 750px;
margin-right: auto;
margin-left: auto;
#media only screen and (max-width: 600px) {
max-width: 80%;
}
`;
export const Wrapper = styled.div`
padding: 10px 0px;
`;
I've tried to add this code but still doesnt working
-webkit-transition: all 0.4s ease-in;
-moz-transition: all 0.4s ease-in;
-o-transition: all 0.4s ease-in;
transition: all 0.4s ease-in;
Try to replace the return block with the following:
return (
<Wrapper>
{isOpen && <AccordionButton onClick={handleClick}>
{title} <BsChevronUp />
</AccordionButton>}
{!isOpen && <AccordionButton onClick={handleClick}>
{title} <BsChevronDown />
</AccordionButton>}
<AccordionContent isOpen={isOpen}>
<p>{text}</p>
</AccordionContent>
</Wrapper>)
and we can also delete the function returnIcon - we don't need it

Mapped buttons that have opacity of 0 are showing, and are overlapping when resizing the window

I've successfully mapped over text and have styled it with transition effects when going from one slide to the next as you can see here:
Following a similar concept with buttons isn't working. There should only be one button active per slide like you see here:
I want the buttons to have the same effect as the text, but I'm getting behaviors like you see here:
As you can see, there is no transition effect on the button when clicking to the second slide, and it also appears in a lower spot.
And lastly, when resizing the window, buttons are overlapping like you see here:
Don't know what to try next.
Here's the ImageSlider component:
import { useState } from "react";
import { SliderData } from "../data";
import { categories } from "../data";
import ShopNowButtonActive from "./ShopNowButtonActive";
import { IoIosArrowBack } from "react-icons/io";
import { IoIosArrowForward } from "react-icons/io";
import "./ImageSlider.css";
import ShopNowButton from "./ShopNowButton";
const ImageSlider = ({ slides }) => {
const [current, setCurrent] = useState(0);
const length = slides.length;
const nextSlide = () => {
setCurrent(current === length - 1 ? 0 : current + 1);
};
const prevSlide = () => {
setCurrent(current === 0 ? length - 1 : current - 1);
};
return (
<div className="slider">
<IoIosArrowBack className="left-arrow" onClick={prevSlide} />
{SliderData.map((slide, index) => (
<div key={slide.id}>
<img
src={slide.img}
alt=""
className={index === current ? "slide active" : "slide"}
/>
<div className="info-container">
<div className={index === current ? "title active" : "title"}>
{slide.title}
</div>
<div className={index === current ? "desc active" : "desc"}>
{slide.desc}
</div>
{categories.map((item, index) =>
index === current ? (
<ShopNowButtonActive item={item} />
) : (
<ShopNowButton item={item} />
)
)}
</div>
</div>
))}
<IoIosArrowForward className="right-arrow" onClick={nextSlide} />
</div>
);
};
export default ImageSlider;
The css file:
.slider {
height: 90vh;
margin-bottom: 0.5rem;
}
.left-arrow {
position: absolute;
top: 45%;
left: 32px;
font-size: 2rem;
cursor: pointer;
opacity: 0.5;
z-index: 1;
}
.slide.active {
opacity: 1;
width: 100%;
height: 88%;
object-fit: cover;
object-position: center;
-webkit-clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0% 0%);
clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0% 0%);
}
.slide {
opacity: 0;
transition: 500ms opacity ease-in-out;
width: 100%;
height: 88%;
object-fit: cover;
object-position: center;
position: absolute;
-webkit-clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0% 0%);
clip-path: polygon(100% 0, 100% 80%, 50% 100%, 0 80%, 0% 0%);
}
.info-container {
display: flex;
flex-direction: column;
width: 40%;
height: 100%;
position: absolute;
top: 45%;
right: 30px;
}
.title.active {
opacity: 1;
transition-delay: 700ms;
font-size: 4rem;
}
.title {
opacity: 0;
transition: 200ms opacity ease-in-out;
font-size: 4rem;
}
.desc.active {
opacity: 1;
padding-top: 1.5em;
transition-delay: 700ms;
font-size: 1.25rem;
font-weight: 500;
letter-spacing: 3px;
}
.desc {
opacity: 0;
padding-top: 1.5em;
transition: 200ms opacity ease-in-out;
font-size: 1.25rem;
font-weight: 500;
letter-spacing: 3px;
}
.right-arrow {
position: absolute;
top: 45%;
right: 32px;
font-size: 2rem;
cursor: pointer;
opacity: 0.5;
z-index: 1;
}
The ShopNowButtonActive component:
import React from "react";
import styled from "styled-components/macro";
import { Link } from "react-router-dom";
const ButtonActive = styled.button`
opacity: 1;
padding: 0.5rem;
margin-top: 2.5rem;
width: 8rem;
font-size: 20px;
background-color: transparent;
cursor: pointer;
transition-delay: 700ms;
`;
const ShopNowButtonActive = ({ item }) => {
return (
<Link to={`/products/${item.cat}`}>
<ButtonActive>SHOP NOW</ButtonActive>
</Link>
);
};
export default ShopNowButtonActive;
And finally, the ShopNowButton component:
import React from "react";
import styled from "styled-components/macro";
import { Link } from "react-router-dom";
const Button = styled.button`
opacity: 0;
/* display: none; */
padding: 0.5rem;
margin-top: 2.5rem;
width: 8rem;
font-size: 20px;
background-color: transparent;
cursor: pointer;
transition: 200ms opacity ease-in-out;
`;
const ShopNowButton = ({ item }) => {
return (
<Link to={`/products/${item.cat}`}>
<Button>SHOP NOW</Button>
</Link>
);
};
export default ShopNowButton;
(Sorry for the use of both an external css file and styled components.)
Any suggestions?
I have recreated the above scenario using some static data. I have modified some of the css. It is working as expected. I also observed that the only major difference between ShopNowButton and ShopNowButtonActive was opacity property which hides the element. The reason you are observing 2 buttons because they were all there in the dom actually.(They were not hiding properly due to which we are observing more shop now buttons and every time we click on next icon the corresponding button is being displayed. Basically all the buttons are there on the page itself.)
Please find the sandbox url below.
https://codesandbox.io/s/stackoverflow-6u05e7?file=/src/ImageSlider/ImageSlider.js

Closing modal window by clicking on backdrop (ReactJS)

Could you please help me with one issue? I'd like to make a closing modal window by clicking on backdrop (using ReactJS). But in result window is closing even i click on modal window (at any position).
Here is my code:
import React from "react";
import { Fragment } from "react";
import ReactDOM from "react-dom";
import "./_Modal.scss";
const Backdrop = (props) => {
return (
<div className="backdrop" onClick={props.onClose}>
{props.children}
</div>
);
};
const ModalOverlay = (props) => {
return <div className="modal">{props.children}</div>;
};
const portalItem = document.getElementById("overlays");
const Modal = (props) => {
return (
<Fragment>
{ReactDOM.createPortal(
<Backdrop onClose={props.onClose}>
<ModalOverlay>{props.children}</ModalOverlay>
</Backdrop>,
portalItem
)}
</Fragment>
);
};
export default Modal;
And here is CSS:
.backdrop {
position: fixed;
top:0;
left: 0;
width: 100%;
height: 100vh;
z-index: 20;
background-color: rgba(0,0,0, 0.7);
display: flex;
justify-content: center;
align-items: flex-start;
overflow: auto;
padding-bottom: 15vh;
}
.modal {
position: relative;
max-width: 70%;
top: 5vh;
background-color: $darkgrey;
padding: 1rem;
border-radius: 1.5rem;
box-shadow: 0 1rem 1rem rgba(0,0,0, 0.25);
z-index: 30;
}
}
I'm just start to learning frontend, therefore do not judge strictly )
Just for understanding other people: after adding event.stopPropagation() in ModalOverlay everything works!
const ModalOverlay = (props) => {
return (
<div
className="modal"
onClick={(event) => {
event.stopPropagation();
}}
>
{props.children}
</div>
);
};

Custom arrow Swiper Slider + Next.js + Sass

I'm using the slider swiper in a project developed in Next.JS and I'm using Sass to do the styling. But when I'm going to use the swiper classes, as mandated by the documentation, to style the arrows, it doesn't work.
I need the arrows to be outside the component, not overlapping.
CSS
.swiper-button-next,
.swiper-button-prev {
background: red;
position: absolute;
top: 50%;
width: calc(var(--swiper-navigation-size) / 44 * 27);
height: var(--swiper-navigation-size);
margin-top: calc(0px - (var(--swiper-navigation-size) / 2));
z-index: 10;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
color: var(--swiper-navigation-color, var(--swiper-theme-color));
}
.swiper-button-next.swiper-button-disabled,
.swiper-button-prev.swiper-button-disabled {
opacity: 0.35;
cursor: auto;
pointer-events: none;
}
.swiper-button-next:after,
.swiper-button-prev:after {
background: red;
font-family: swiper-icons;
font-size: var(--swiper-navigation-size);
text-transform: none !important;
letter-spacing: 0;
text-transform: none;
font-variant: initial;
line-height: 1;
}
.swiper-button-prev,
.swiper-container-rtl .swiper-button-next {
left: 10px;
right: auto;
}
.swiper-button-prev:after,
.swiper-container-rtl .swiper-button-next:after {
content: "prev";
color: #000;
}
.swiper-button-next,
.swiper-container-rtl .swiper-button-prev {
right: 10px;
left: auto;
}
.swiper-button-next:after,
.swiper-container-rtl .swiper-button-prev:after {
content: "next";
}
.swiper-button-next.swiper-button-white,
.swiper-button-prev.swiper-button-white {
--swiper-navigation-color: #ffffff;
}
.swiper-button-next.swiper-button-black,
.swiper-button-prev.swiper-button-black {
--swiper-navigation-color: #000000;
}
.swiper-button-lock {
display: none;
}
I've tried changing the styles, but nothing reflects on the component. If I change styles by browser it works normally.
Changing the basic arrows styles is pretty simple - take a look at the following codesandbox: https://codesandbox.io/s/stoic-shaw-q35wq?file=/src/styles.scss
.swiper-button-prev, .swiper-button-next {
top: 45%;
width: 40px;
height: 40px;
background: #fff;
border: 1px solid gray;
border-radius: 50%;
color: blue;
font-weight: 700;
outline: 0;
transition: background-color .2s ease, color .2s ease;
&::after {
font-size: 16px;
}
}
.swiper-button-prev {
&:after {
position: relative;
left: -1px;
}
}
.swiper-button-next {
&:after {
position: relative;
left: 1px;
}
}
.swiper-button-prev, .swiper-container-rtl .swiper-button-next {
left: 10px;
right: auto;
}
.swiper-button-next, .swiper-container-rtl .swiper-button-prev {
right: 10px;
left: auto;
}
.swiper-button-prev.swiper-button-disabled, .swiper-button-next.swiper-button-disabled {
opacity: 0;
cursor: auto;
pointer-events: none;
}
Moving the arrows outside, however, is a bit more tricky. In the example above I've used a little CSS tricks (negative margin and corresponding padding) and some overflows to get it working but it might not be enough for your use case.
You would have to create your own next/previous elements:
import React from "react";
import { Navigation, Pagination, Scrollbar, A11y, Controller } from "swiper";
import { Swiper, SwiperSlide } from "swiper/react";
// Import Swiper styles
import "swiper/css";
import "swiper/css/navigation";
import "swiper/css/pagination";
import "swiper/css/scrollbar";
import "./styles.scss";
const image = "https://source.unsplash.com/featured/300x201";
export default function App() {
const images = new Array(6).fill({ url: image });
const [swiper, setSwiper] = React.useState();
const prevRef = React.useRef();
const nextRef = React.useRef();
React.useEffect(() => {
if (swiper) {
console.log("Swiper instance:", swiper);
swiper.params.navigation.prevEl = prevRef.current;
swiper.params.navigation.nextEl = nextRef.current;
swiper.navigation.init();
swiper.navigation.update();
}
}, [swiper]);
return (
<div className="App">
<div className="carousel-container">
<div className="swiper-button" ref={prevRef}>
prev
</div>
<Swiper
modules={[Navigation, Pagination, Scrollbar, A11y, Controller]}
className="external-buttons"
spaceBetween={24}
slidesPerView={1}
navigation={{
prevEl: prevRef?.current,
nextEl: nextRef?.current
}}
updateOnWindowResize
observer
observeParents
initialSlide={2}
onSwiper={setSwiper}
>
{images.map((image, index) => (
<SwiperSlide key={index}>
<img
height="200"
width="300"
alt="img"
className="image"
src={image.url}
/>
</SwiperSlide>
))}
</Swiper>
<div className="swiper-button" ref={nextRef}>
next
</div>
</div>
</div>
);
}
Complete example - https://codesandbox.io/s/prod-darkness-o483y?file=/src/App.js
Important - the examples are using Swiper v7
Here is the best way to add custom arrows:
import React, { useRef } from "react";
// For Typescript
// import SwiperCore from "swiper";
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
const SliderComponent = () => {
const swiperRef = useRef();
// For Typescript!
// const swiperRef = useRef<SwiperCore>();
const sliderSettings = {
440: {
slidesPerView: 1,
spaceBetween: 30,
},
680: {
slidesPerView: 2,
spaceBetween: 30,
},
1024: {
slidesPerView: 3,
spaceBetween: 30,
},
};
return (
<div>
<button onClick={() => swiperRef.current?.slidePrev()}>Prev</button>
<Swiper
slidesPerView={3}
breakpoints={sliderSettings}
onBeforeInit={(swiper) => {
swiperRef.current = swiper;
}}
>
<SwiperSlide>
Slide 1
</SwiperSlide>
<SwiperSlide>
Slide 2
</SwiperSlide>
<SwiperSlide>
Slide 3
</SwiperSlide>
<SwiperSlide>
Slide 4
</SwiperSlide>
<SwiperSlide>
Slide 5
</SwiperSlide>
</Swiper>
<button onClick={() => swiperRef.current?.slideNext()}>Next</button>
</div>
);
};
export default SliderComponent;
hamza liaqat's answer is correct, but for typescript you need to add
import { Swiper as SwiperCore } from 'swiper/types';

How to change background color with toggle button in React?

In Weather project, I have toggle button for Day/Night mode. When toggled it should change background color but it fills the entire page above the components which isn't desirable. Is there any appropriate solution?
Below is the reference
DayNightMode.js
const DayNightMode = () => {
return (
<div className="switch-box">
<div className="switch">
<label for="toggle">
<input id="toggle" className="toggle-switch" type="checkbox" />
<div className="sun-moon">
<div className="dots">
</div>
</div>
<div className="background">
<div className="stars1"></div>
<div className="stars2"></div>
</div>
<div className="fill"></div>
</label>
</div>
</div>
);
};
export default DayNightMode;
DayNightMode.css
* {
box-sizing: border-box;
}
.switch-box {
margin-left: 30%;
/* margin-top: -5%; */
}
.container {
/* height: calc(100% - 2.5rem); */
/* background: #f4f4f4; */
/* display: flex; */
/* justify-content: center; */
/* align-items: center;*/
}
.switch {
position: relative;
/* overflow: hidden; */
width: 8.6rem;
/* height: 2rem; */
}
.switch input {
position: absolute;
top: 0;
left: 0;
z-index: 2;
opacity: 0;
}
.switch label {
cursor: pointer;
}
.background {
z-index: 1;
position: absolute;
width: 6.5rem;
height: 1.8rem;
border-radius: 2.5rem;
border: 0.25rem solid #202020;
background: linear-gradient(to right, #484848 0%, #202020 100%);
transition: all 0.3s;
margin-top: -22px;
opacity: 0.8;
}
.fill {
/* background: #484848;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0; */
}
.switch input:checked ~ .fill {
background: #e9f8fd;
}
/* .fill {
position: fixed;
top: 0;
right: 0;
bottom: 2rem;
left: 0;
background: #484848;
transition: 0.75s all ease;
} */
/* .switch input:checked ~ .fill {
background: #E9F8FD;
} */
/* Stars */
.stars1,
.stars2 {
position: absolute;
height: 0.3rem;
width: 0.3rem;
background: #ffffff;
border-radius: 50%;
transition: 0.3s all ease;
}
.stars1 {
top: 2px;
right: 20px;
}
.stars2 {
top: 20px;
right: 35px;
}
.stars1:after,
.stars1:before,
.stars2:after,
.stars2:before {
position: absolute;
content: "";
display: block;
height: 0.25rem;
width: 0.25rem;
background: #ffffff;
border-radius: 50%;
transition: 0.2s all ease;
}
.stars1:after {
top: 2px;
right: 20px;
}
.stars1:before {
top: 12px;
right: -12px;
}
.stars2:after {
top: -20px;
right: -20px;
}
.stars2:before {
top: -24px;
right: -30px;
}
.sun-moon {
z-index: 2;
position: absolute;
left: 0;
display: inline-block;
height: 1.5rem;
width: 1.5rem;
margin: 0.12rem;
background: #fffdf2;
border-radius: 50%;
transition: all 0.5s ease;
margin-top: -20.5px;
/* Default to Moon */
border: 0.2rem solid #dee2c6;
}
.sun-moon .dots {
position: absolute;
top: 0.5px;
left: 42px;
height: 0.2rem;
width: 0.2rem;
background: #efeedb;
border: 0.25rem solid #dee2c6;
border-radius: 50%;
transition: 0.4s all ease;
}
.sun-moon .dots:after,
.sun-moon .dots:before {
position: absolute;
content: "";
display: block;
height: 0.25rem;
width: 0.25rem;
background: #efeedb;
border: 0.25rem solid #dee2c6;
border-radius: 50%;
transition: 0.4s all ease;
}
.sun-moon .dots:after {
top: -8px;
left: -26px;
}
.sun-moon .dots:before {
top: 10px;
left: -10px;
}
/* Transition to Sun */
.switch input:checked ~ .sun-moon {
left: calc(100% - 4rem);
background: #f5ec59;
border-color: #e7c65c;
transform: rotate(-25deg);
}
.switch input:checked ~ .sun-moon .dots,
.switch input:checked ~ .sun-moon .dots:after,
.switch input:checked ~ .sun-moon .dots:before {
background: #ffffff;
border-color: #ffffff;
}
.switch input:checked ~ .sun-moon .dots {
height: 1.2rem;
width: 1.2rem;
top: -10px;
left: -20px;
transform: rotate(25deg);
}
.switch input:checked ~ .sun-moon .dots:after {
height: 0.65rem;
width: 0.65rem;
top: 2px;
left: -12px;
}
.switch input:checked ~ .sun-moon .dots:before {
height: 0.4rem;
width: 0.4rem;
top: 6px;
left: 14px;
}
.switch input:checked ~ .background .stars1,
.switch input:checked ~ .background .stars2 {
opacity: 0;
transform: translateY(2rem);
}
.switch input:checked ~ .background {
border: 0.25rem solid #78c1d5;
background: linear-gradient(to right, #78c1d5 0%, #bbe7f5 100%);
}
Form.js (DayNight Toggle button defined here)
import React from 'react'
import { ArrowTooltip } from './ArrowTooltip'
import gps from '../images/gps.png'
import 'react-toastify/dist/ReactToastify.css';
import Autosuggest from 'react-autosuggest';
import { highlight } from './Helper'
import cities from 'cities.json';
import Button from 'react-bootstrap/Button'
import './Form.css';
import { MDBContainer,
MDBRow,
MDBCol,
MDBCard,
MDBCardBody,
MDBCardHeader,
MDBBtn} from 'mdbreact'
import DayNightMode from './DayNightMode';
class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
value: '',
suggestions: [],
newsValue: '',
weatherValue: ''
};
}
onChange = (event, { newValue}) => {
this.setState({
value: newValue,
});
};
render(){
return (
<div>
<MDBContainer style={{height: '480px', marginTop: '25px'}}>
<MDBRow>
<MDBCol>
<MDBCard style={sectionStyle}></MDBCard>
<MDBCard style={{zIndex:'1', background: 'none'}}>
<MDBCardBody>
{/* Here Toggle button is defined */}
<DayNightMode/>
<form>
<div width="100%">
<ArrowTooltip title="Track Location" placement="top">
<span style={{width:'10%', display:'inline-block', cursor:'pointer'}}
onClick={this.props.fetchWeather}>
<img src={gps} width="25px" height="25px" />
</span>
</ArrowTooltip>
</div>
<br/>
<div className="text-center mt-4">
<Button variant="info"
className="mb-3 btn-block"
type="submit"
value={inputProps.value}
onClick={e => this.onClick(e)}
style={{background: '#e0f7fa', opacity:'0.6',
borderRadius: '10px',fontFamily: 'Josefin Sans',
boxShadow: '0 8px 6px -6px black'}}
>Search Weather</Button>
</div>
</form>
</MDBCardBody>
</MDBCard>
</MDBCol>
</MDBRow>
</MDBContainer>
</div>
)
}
}
export default Form;
App.js (Parent File)
import React from "react";
import "./App.css";
import Form from "./components/Form";
import { ToastContainer, toast, Bounce } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import WeatherAndNews from "./components/WeatherAndNews";
import moment from "moment-timezone";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
newsValue: "",
weatherValue: ""
};
}
handleNews = async (data) => {
this.setState({
newsValue: data
});
};
handleWeather = async (data) => {
this.setState({
weatherValue: data
});
};
render() {
return (
<React.Fragment>
<div className="main-container">
<div className="form-container">
<Form
newsValue={this.state.newsValue}
weatherValue={this.state.weatherValue}
/>
<ToastContainer transition={Bounce} className="toast-background" />
</div>
<div className="body-container">
<WeatherAndNews />
</div>
</div>
</React.Fragment>
);
}
}
export default App;
My intention is that background color of the page should be changed on toggle
Following is the Codesandbox link https://codesandbox.io/s/2huux
Steps you need to do to achieve this:
Create a variable named 'isDayMode' in App.js component
Create a function with the name 'handleDayNightToggle' in App.js which can update that value to true or false on the basis of the checkbox selected
Pass the reference of the function as props to the Form component
Again pass the reference of function 'handleDayNightToggle' from Form to DayNightMode component
There create an onClick function for the checkbox and make it call the 'handleDayNightToggle' passed as props. So any time the checkbox is clicked this function calls the 'handleDayNightToggle' of the App component.
Finally use the flag 'isDayMode' in App component to understand whether the day is selected or night and accordingly change the classes to update background color.
Updated your project with the above steps, take a look into it - https://codesandbox.io/s/async-cache-r1poy

Resources