I have one problem, I don't know how make this component to work like RWD.
import "../css/stack.css";
import React, { useEffect, useState } from "react";
import css from "../pictures/css.png";
import react from "../pictures/react.png";
import js from "../pictures/js.png";
import ts from "../pictures/ts.png";
function Stack() {
const [scrollY, setScrollY] = useState(window.scrollY);
const [jsLogo, setJsLogo] = useState("first");
const [reactLogo, setReactLogo] = useState("");
const [tsLogo, setTsLogo] = useState("");
const [cssLogo, setCssLogo] = useState("");
useEffect(() => {
window.addEventListener("scroll", () => {
setScrollY(window.scrollY);
});
}, []);
useEffect(() => {
if (scrollY > 1400) {
setJsLogo("first");
}
if (scrollY <= 1700 && scrollY > 1400) {
setJsLogo("fromRight");
}
if (scrollY > 1700) {
setJsLogo("goLeft");
setReactLogo("fromBottom");
} else setReactLogo("");
if (scrollY > 2000) {
setReactLogo("goTop");
setTsLogo("fromRight");
} else setTsLogo("");
if (scrollY > 2300) {
setTsLogo("goLeft");
setCssLogo("fromTop");
} else setCssLogo("");
if (scrollY > 2600) {
}
}, [scrollY]);
return (
<div className="sticky">
<div id="Stack">
<div
className="divForH1"
style={{
position: "absolute",
top: "0px",
letterSpacing: "1px",
}}
>
<h1 className="StackH1">Stack technologiczny</h1>
</div>
<img src={js} alt="js" className={`${jsLogo} sizePng`} />
<img
src={react}
alt="js"
className={`${reactLogo} second ${scrollY > 1700 && "first"} sizePng`}
/>
<img
src={ts}
alt="js"
className={`${tsLogo} second ${scrollY > 2000 && "first"} sizePng`}
/>
<img
src={css}
alt="js"
className={`${cssLogo} second ${scrollY > 2300 && "first"} sizePng`}
/>
</div>
</div>
);
}
export default Stack;
I change image inside container with css property sticky and in desktop this work like i want, but in phone, image start change before how css property sticky will start working.
I know that this problem is in rigidly property "px" but i don't know how fix this.
I want to start image change when the sticky container starts to get sticky :)
Related
Good morning
I would like to add a block div on my leaflet card with text in the div Reactjs.
but it does not show on the map. It is displayed under the map, I tried with z-index but I did not succeed
anyone have a solution please?
<div >
<MapContainer center={center} zoom={zoom} style={{ height: "90vh", opacity: 'O,33' }}>
<TileLayer attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
<Markers marker={mark} />
<div>Test</div>
</MapContainer >
</div>);```
You can use z-index, however you will also have to set position to something other than default static. e.g. position: absolute
I would recommend to look into the built in leaflet-control classes. I use a custom controller to add stuff above the map:
import L from "leaflet";
import React, { useEffect, useRef } from "react";
const ControlClasses = {
bottomleft: "leaflet-bottom leaflet-left",
bottomright: "leaflet-bottom leaflet-right",
topleft: "leaflet-top leaflet-left",
topright: "leaflet-top leaflet-right",
};
type ControlPosition = keyof typeof ControlClasses;
export interface LeafLetControlProps {
position?: ControlPosition;
children?: React.ReactNode;
offset?: [number, number];
}
const LeafletControl: React.FC<LeafLetControlProps> = ({
position,
children,
offset = [0, 0],
}) => {
const divRef = useRef(null);
useEffect(() => {
if (divRef.current) {
L.DomEvent.disableClickPropagation(divRef.current);
L.DomEvent.disableScrollPropagation(divRef.current);
}
});
return (
// #ts-ignore
<div
style={{
marginLeft: offset[0],
marginTop: offset[1],
}}
ref={divRef}
className={position && ControlClasses[position]}
>
<div className={"leaflet-control"}>{children}</div>
</div>
);
};
export default LeafletControl;
I am trying to convert my existing code from Next js 12 to 13. But I am unable to make it work. How should I transform to make it work? Getting errors like you can't use "useState" etc.
import { useState } from 'react';
import Head from 'next/head';
import { loadData } from './api/post';
import {
Section,
Cover,
SocialNetworks,
BuyMeCoffee,
Title,
PostGrid,
Post,
Button
} from '../components';
const LOAD_MORE_STEP = 4;
export default function Home({ initialPosts, total }) {
const [ posts, setPosts ] = useState(initialPosts);
const [ loadedAmount, setLoadedAmount ] = useState(LOAD_MORE_STEP);
const [ loading, setLoading ] = useState(false);
const showLoadButton = total > loadedAmount;
const getMorePosts = async () => {
setLoading(true);
try {
const data = await fetch(`/api/post?start=${loadedAmount}&end=${loadedAmount + LOAD_MORE_STEP}`).then((response) => response.json());
setLoadedAmount(loadedAmount + LOAD_MORE_STEP);
setPosts([...posts, ...data.posts])
setLoading(false);
} catch (error) {
console.log(error);
setLoading(false);
}
};
return (
<div style={{
marginBottom: '1rem',
}}>
<Head>
<title>My blog</title>
</Head>
<Section>
<Cover title="Elena<br />Litvinova" />
<SocialNetworks />
<BuyMeCoffee />
</Section>
<Section>
<Title>New Post</Title>
<PostGrid>
{posts.map((post) => (
<Post
key={post._id}
{...post}
/>
))}
</PostGrid>
{showLoadButton && (
<div style={{
display: 'flex',
justifyContent: 'center',
}}>
<Button
disabled={loading}
onClick={getMorePosts}
>
Load more posts...
</Button>
</div>
)}
</Section>
</div>
)
}
export async function getServerSideProps() {
const { posts, total } = await loadData(0, LOAD_MORE_STEP);
return {
props: {
initialPosts: posts,
total
},
}
}
React hooks are only available on the client. You have to add 'use client' to the top of your file, if it is a client component. In Next.js 13 all components are React server component by default. Here are the docs for server and client components in Next.js
I would also recommend you to fetch your data with #tanstack/react-query.
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 just started working with Framer motion and Nextjs, and I ran into a problem where I am unable to get the exit property to animate. The code below shows that I am trying to toggle the word 'Hello' on and off, and while the word appears when toggled on, the exit animation does not trigger when removed. The Framer API docs suggest that AnimatePresence needs to wrap the motion.div as seen below in order for the exit animation to trigger, but this has not fixed the issue.
Any help would be appreciated.
import React from "react";
import classes from "./FramerMotion.module.css";
import { motion, AnimatePresence, } from "framer-motion";
import { useState } from "react";
function FramerMotion() {
const [words, setWords] = useState(true);
const toggleWords = (event) => {
setWords(words === false);
console.log(words);
};
const codeVariant = {
start: {
opacity: 0,
},
middle: {
opacity: 1,
transition: {
duration: 3,
},
},
end: {
opacity: 0,
transition: {
duration: 3,
},
},
};
return (
<>
<div className={classes.container}>
{words && (
<AnimatePresence>
<motion.h1
key="modal"
variants={codeVariant}
initial="start"
animate="middle"
exit="end"
>
Hello
</motion.h1>
</AnimatePresence>
)}
</div>
<button onClick={toggleWords}>Show/Hide</button>
</>
);
}
export default FramerMotion;
I solved this problem. The problem was that AnimatePresence was improperly placed.
Fix:
return (
<>
<div className={classes.container}>
<AnimatePresence>
{words && (
<motion.h1
key="modal"
variants={codeVariant}
initial="start"
animate="middle"
exit="end"
>
Hello
</motion.h1>
)}
</AnimatePresence>
</div>
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.