I am working with custom Transition component and my inline styling just wont apply. I tried everything what is in my power and just got myself angry. Can somebody explain why this doesn't work.
Modal show itself on initial load and by clicking on button for show or not show this doesn't react. I mean state updates correctly (this console.log shows 0 and 1 when it should) but styling just wont apply.
import classes from "./App.module.css";
import ReactDOM from "react-dom";
import React from "react";
import Modal from "./components/Modal/Modal";
import List from "./components/List/List";
import Backdrop from "./components/Backdrop/Backdrop";
import { useState } from "react";
import Transition from "react-transition-group/cjs/Transition";
function App() {
const [modalOpen, setModalOpen] = useState(false);
const onOpenModalHandler = () => {
setModalOpen(true);
};
const onCloseModalHandler = () => {
setModalOpen(false);
};
return (
<div className={classes["App"]}>
<h1>React Animations</h1>
<Transition in={modalOpen} timeout={1000} onMountEnter onMountExit>
{(state) => {
console.log(state);
console.log(state === "exiting" || state === "exited" ? 0 : 1);
return ReactDOM.createPortal(
<Modal
closeModal={onCloseModalHandler}
modalState={modalOpen}
style={{
transition: `opacity 300ms ease-out`,
opacity: state === "exiting" || state === "exited" ? 0 : 1,
}}
/>,
document.getElementById("modal")
);
}}
</Transition>
{modalOpen &&
ReactDOM.createPortal(
<Backdrop />,
document.getElementById("backdrop")
)}
<button className={"Button"} onClick={onOpenModalHandler}>
Open Modal
</button>
<h3>Animating Lists</h3>
<List />
</div>
);
}
export default App;
Modal
import classes from "./Modal.module.css";
const Modal = (props) => {
const classNames = props.modalState
? `${classes["modal-open"]} ${classes["Modal"]}`
: `${classes["modal-close"]} ${classes["Modal"]}`;
const onCloseModalHandler = () => {
props.closeModal();
};
return (
<div className={classNames}>
<h1>A Modal</h1>
<button className="Button" onClick={onCloseModalHandler}>
Dismiss
</button>
</div>
);
};
export default Modal;
Related
I am working on a project with a setup combination of react, tailwind and react icons. In my project multiple sliders are required (some has navigation, some has pagination etc…)
So, I created a slider factory component Carousel and controlling variation through props
// Carousel/index.jsx
import { Children, useState } from "react";
import { v4 as uuidv4 } from "uuid";
import { HiOutlineArrowLeft, HiOutlineArrowRight } from "react-icons/hi";
import { Swiper, SwiperSlide } from "swiper/react";
import { Autoplay, Keyboard, Mousewheel, Navigation, Pagination } from "swiper";
import "swiper/css";
import "swiper/css/pagination";
import "swiper/css/navigation";
import NextSlideBtn from "./NextSlideBtn";
import PrevSlideBtn from "./PrevSlideBtn";
const Carousel = ({
children,
loop,
pagination,
navigation,
autoplay,
breakpoints,
}) => {
const childrenArray = Children.toArray(children);
const [swiperRef, setSwiperRef] = useState();
return (
<div className="group relative">
<Swiper
className="rounded overflow-hidden"
onSwiper={setSwiperRef}
modules={[
Autoplay,
Keyboard,
Mousewheel,
Pagination,
Navigation,
]}
mousewheel
keyboard
grabCursor
loop={loop || false}
autoplay={
autoplay && {
delay: 5000,
disableOnInteraction: true,
}
}
spaceBetween={breakpoints && 20}
breakpoints={
breakpoints && {
450: {
slidesPerView: 2,
},
768: {
slidesPerView: 3,
},
1536: {
slidesPerView: 4,
},
}
}
pagination={
pagination && {
clickable: true,
}
}
>
{childrenArray.map((item) => (
<SwiperSlide key={uuidv4()}>{item}</SwiperSlide>
))}
</Swiper>
{navigation && (
<div className="hidden group-hover:block">
<PrevSlideBtn swiperRef={swiperRef}>
<HiOutlineArrowLeft className="text-violet-600" />
</PrevSlideBtn>
<NextSlideBtn swiperRef={swiperRef}>
<HiOutlineArrowRight className="text-violet-600" />
</NextSlideBtn>
</div>
)}
</div>
);
};
export default Carousel;
// Carousel/NextSlideBtn.jsx
const NextSlideBtn = ({ children, swiperRef }) => {
const handleNextSlide = () => swiperRef.slideNext();
return (
<button
onClick={handleNextSlide}
className="absolute z-50 top-1/2 -translate-y-1/2 -right-2 translate-x-2 bg-white shadow-md rounded-full p-3"
>
{children}
</button>
);
};
export default NextSlideBtn;
// Carousel/PrevSlideBtn.jsx
const PrevSlideBtn = ({ children, swiperRef }) => {
const handlePrevSlide = () => swiperRef.slidePrev();
return (
<button
onClick={handlePrevSlide}
className="absolute z-50 top-1/2 -translate-y-1/2 -left-2 -translate-x-2 bg-white shadow-md rounded-full p-3"
>
{children}
</button>
);
};
export default PrevSlideBtn;
One of the requirement was to create custom navigation button, which I managed to accomplish as you can see in the code above, but for more visibility I am marking the flow in short
// Carousel/index.jsx
const [swiperRef, setSwiperRef] = useState();
<div>
<Swiper
onSwiper={setSwiperRef}
...
>
...
</Swiper>
<PrevSlideBtn swiperRef={swiperRef} />
<NextSlideBtn swiperRef={swiperRef} />
</div>
// Carousel/NextSlideBtn.jsx
const NextSlideBtn = ({ children, swiperRef }) => {
const handleNextSlide = () => swiperRef.slideNext();
return (
<button
onClick={handleNextSlide}
...
>
{children}
</button>
);
};
export default NextSlideBtn;
// Carousel/PrevSlideBtn.jsx
const PrevSlideBtn = ({ children, swiperRef }) => {
const handlePrevSlide = () => swiperRef.slidePrev();
return (
<button
onClick={handlePrevSlide}
...
>
{children}
</button>
);
};
export default PrevSlideBtn;
Couple of github issues, stackoverflow questions and swiper docs helped me out to accomplish this, and it was pretty straight forward to understand.
Now my question is how can I customize swiper react pagination (like radio buttons which some websites use, or any other styles…) using tailwind and I want to make it as a separate component like I did for navigation buttons.
I’ve tried many solutions eg:
const paginationBullets = {
type: "custom",
clickable: true,
renderCustom: (_, current, total) => {
return <MyCustomSwiperPaginationComponent current={current} total={total} />;
},
};
But nothing seems to work as expected.
Please help me out.
Component separation is my goal.
I tried to send show_request value to TopMenu component, which is external component, but it did not pass. In TopMenu, If I output show_request on console it responses undefined
import React, { useState } from "react";
import TopMenu from "../../components/top-menu/top-menu";
import { projects } from "./project.data";
import "./projects.scss";
const Projects = () => {
return (
<div className="projects-page">
<div className="request"
onClick={() => <TopMenu show_request={true} />}
>
DROP REQUEST
</div>
</div>
);
};
export default Projects;
I did this, and I thought show_request=true in TopMenu
<div className="request"
onClick={() => <TopMenu show_request={true} />}
>
DROP REQUEST
</div>
My code In TopMenu
const TopMenu = ({ show_request }) => {
console.log(show_request); // It should be show_request=true, but it is undefined
}
I am trying to programatically hide a div when a button is clicked.
Therefore I have written the following code, but it is not working (Div is still there):
import React, {useState} from 'react';
import './Button.css';
export function Button() {
const [click, setClick] = useState(false);
const hideDiv = () => {
var display = 'block';
if (click){
display = 'none';
setClick(false);
}else{
display = 'block';
setClick(true);
}
return ([
document.getElementById('main').style.display = {display}
])
};
return(
<button className='btn' onClick={() => setClick(true), hideDiv}>Some button!</button>
);
};
I "debugged" the application with an alert and the correct display is coming, but it seems that I am missing something when applying it to the div style.
What am I missing here?
Try this approach,
export function Button() {
const [display, setDisplay] = useState("block");
const hideDiv = () => {
setDisplay(display === "none" ? "block" : "none");
};
return (
<>
{display === "block" && <div>MY DIV</div>}
<button className="btn" onClick={hideDiv}>
Some button!
</button>
</>
);
}
CODESANDBOX - https://codesandbox.io/s/wizardly-water-kf0md?file=/src/App.js
As #dai commented, you shouldn't interact directly with the DOM inside React (because it actually renders a virtual one).
Try using states instead, for example:
import React, {useState} from 'react';
import './Button.css';
export function Button() {
const [display, setDisplay] = useState(true);
const hideDiv = () => {
setDisplay(!display);
};
return (
<>
{display && (<div id='main'></div>)}
<button className='btn' onClick={hideDiv}>Some button!</button>
<>
);
};
If the div you want to add is an other component, you should use contexts instead.
I am working with carousel cards. I am using react bootstrap. It is not showing me the carousal items (image). Api is working fine.
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { useEffect } from "react";
import { getBanners } from "../container/home.actions";
import Carousel from "react-bootstrap/Carousel";
import logo from "../../../../logo.svg";
function Home() {
const dispatch = useDispatch(); // we are getting dispatch object with the help of this, we will dispatch an action.
const banners = useSelector((state) => state.homeReducer.banners);
useEffect(() => {
//component did mount
dispatch(getBanners());
}, []);
const getCarouselItem = (banner) => {
console.log("In Carousel item function..");
return (
<Carousel.Item>
<img
className="d-block w-100"
src={`http://raw.githubusercontent.com/gautam-in/shopping-cart-assignment/master${banner.bannerImageUrl}`}
alt="First banner"
/>
</Carousel.Item>
);
};
return (
banners &&
banners.length > 0 && (
<Carousel>
{banners.forEach((banner) => {
getCarouselItem(banner);
})}
</Carousel>
)
);
}
export default Home;
so i'm trying to make my Navbar fixed to the top of the screen when i have scrolled below the actual Navbar. I am using WayPoints onEnter and onLeave to trigger when i have scrolled past. The issue i'm having is, that when styled is equal to false, the {position:'relative'} i believe makes the site crash and i'm not sure why, or what solution is.
import React, { useEffect, useState } from 'react'
import Navbar from './Navbar'
import { Box, Grid, Card, CardMedia, CardActionArea, Typography, CardContent, CardActions, Button }
from '#material-ui/core'
import Styles from './Styles'
import { Random } from 'react-animated-text'
import { projectSections } from './ListItems'
import { Waypoint } from 'react-waypoint';
const Portfolio = () => {
const [styled, setStyled] = useState(false)
const style = () => (
styled==false
? {
position:'fixed',
width:'100%',
zIndex:99
}
: {position:'relative'}
)
const handleWaypointEnter = () => (
setStyled(!styled) )
const handleWaypointLeave = () => (
setStyled(!styled)
)
return (
<>
<Waypoint
onEnter={handleWaypointEnter}
onLeave={handleWaypointLeave}
>
<div style={style()}>
<Navbar/>
</div>
</Waypoint>
{/* Ignore this for now
<Box style={{position:'relative'}}>
<Box component='div'>
<Typography align='center' className={classes.portTitle}>
<Random
className={classes.portTitle}
text="PORTFOLIO"
effect='pop'
effectChange={.8}
effectDuration={1.3}
/>
</Typography>
<Grid container justify='center' alignItems='center' style={{padding:20}}>
{project()}
</Grid>
</Box>
</Box>
*/}
</>
)
}
Have you tried with return statement in style function.