I am working on a portfolio site with React.js as a self-learning project for my software engineering course. My goal is to make a heavily animated portfolio site.
I am currently experiencing a bug where the entire page freezes up for a bit when using a react-reveal animation on my photo in the about section (About.js component). However, the animation works just fine on the text directly next to the image.
The navbar (Navbar.js component) contains the react-scroll code which is just simple Link to the id of each section. One thing to note is that the animations also work fine if the user manually scrolls. I have also tried in a variety of browsers.
I thought that the issue might have been caused by having too many animations running at once, causing lag, but I tested multiple react-reveal animations together and it has no problem so long as there is no scroll taking place. I also tried delaying the animations, but that led to the same frozen results. I included a video of the problem and the project github linked below.
About.js
...
const About = () => {
return (
<>
<div id='about' className='aboutSection'>
<br />
<div className='aboutBox'>
<div className='aboutText'>
<Fade left><h1>About Me</h1>
<p>Placeholder for purposes of post</p>
</Fade>
</div>
<div className='aboutPicture'>
<Fade right><img src={headshot} id='headshot' /></Fade> {/*This fade is causing the issues*/}
</div>
</div>
</div>
</>
)
}
Navbar.js
...
<div className='mainNav'>
<ul>
{/* <NavLink to='/' exact className='nav' style={{ textDecoration: 'none' }}> */}
<li id='title'><Link to='top' smooth={true} ignoreCancelEvents><button className='navTitleText'>Mitchell Conrad</button></Link></li>
{/* </NavLink> */}
<li className='nav-item'><Link to='about' spy={true} smooth={true} ignoreCancelEvents><Button scrollButton={props.scrollNav}> About </Button></Link></li>
<li className='nav-item'><Link to="projects" spy={true} smooth={true} ignoreCancelEvents><Button scrollButton={props.scrollNav}> Projects </Button></Link></li>
<li className='nav-item'><Link to="resume" spy={true} smooth={true} ignoreCancelEvents><Button scrollButton={props.scrollNav}> Resume </Button></Link></li>
<li id='contact' className='nav-item'><Button onClick={() => modalRef.current.open()}> Contact </Button></li>
</ul>
</div>
...
Video of Issue
Full Project Github Link
I appreciate any advice/direction to take to work around this or fixes. Maybe I am missing something simple here, but I can't figure it out for the life of me.
Related
I am writing a webpage using React. I implemented a swiper on the landing page using Swiper. Its slides include an image and a few text blocks, very typical.
The animation works completely fine and smooth for FireFox, Safari, Edge, etc. However, the swiping motion is very buggy in Chrome. After spending some time to figure out why, I found that the issue can be hot fixed by disabling Chrome ‘Use hardware acceleration when available’ setting option. I also tried enabling Swiper CssMode, but it is not helping.
The webpage is supposed to be smooth to public users, turning HW acceleration off is not a feasible cure. Did anyone encountered similar problems before who can give me some clue?
Another observation I have on my React page is that, upon refreshing the webpage, if I scroll down quickly to the bottom, everything down there (other page content and footer) is blank. They display correctly after 3 seconds of rendering. This problem only occurs in Chrome, with HW acceleration on as well.
<div className='Latest-Swiper Content-Container'>
<Swiper loop={true} navigation={true} id='Latest-Swiper'
// cssMode={true}
observer={true}
uniqueNavElements={false}
onAfterInit={(swiper) => initBackground(swiper)}
onRealIndexChange={(swiper) => updateBackground(swiper)}
modules={[Navigation, Pagination]}
pagination={{
enabled: true,
el: '.Latest-Swiper-Custom-Pagination',
renderBullet: (index, className) => {
return '<span class="' + className + '"></span>';
},
}}
>
{articles.map((article, index) =>
(
<SwiperSlide className={article.category}>
<div className='Latest-Swiper-Title-Wrapper'>
<p className='Latest-Swiper-Title Latest-Swiper-Title-Mobile'>{article.title}</p>
</div>
<div className='Latest-Swiper-Image-Wrapper'>
{/* Post image */}
<img className='Latest-Swiper-Image' src={'sample.jpeg'} alt='' />
</div>
<div className='Latest-Swiper-Desc-Wrapper'>
{/* Desc */}
{article.body}
</div>
</SwiperSlide>
)
)}
</Swiper>
<div className='Latest-Swiper-Custom-Pagination' />
</div >
Thanks in advance.
I'd like to create the desired results as seen here.
Please view in Desktop widescreen. AirBnb results.
As you can see with the AirBnb results, the Map on the Righthand side sticks perfectly into place while allowing the user to scroll down to view the results on the Lefthand side.
I've been trying to figure out how they have achieved this but am reaching some road blocks. I found some luck with implementing this bit of code but there is still a slight amount of vertical scrolling before the bottom of the map snaps into place. I believe it has to do with the h-screen class making the map height: 100vh
<main className="flex">
{/* Results & Filters section - Left side */}
<section className='flex-grow'>
<div className='lg:inline-flex mt-5 mb-5 space-x-3 text-gray-800 whitespace-no-wrap'>
<p className='custom-button'>Cancellation Flexibility</p>
<p className='custom-button'>Type of Place</p>
<p className='custom-button'>Price</p>
<p className='custom-button'>Rooms and Beds</p>
<p className='custom-button'>More Filters</p>
</div>
<div className="flex flex-col">
{/* Search results */}
{searchResults.map(
({ img, location, title, description, star, price, total }) => (
<InfoCard
key={img}
img={img}
location={location}
title={title}
description={description}
star={star}
price={price}
total={total}
/>
))}
</div>
</section>
{/* Map section - Right side */}
<aside className="hidden h-screen w-[50%] sticky xl:inline-flex l:min-w-[600px] top-0">
<Map searchResults={searchResults} />
</aside>
</main>
Some help would be greatly appreciated. I've started a codesandbox to make it easier to see what I'm experiencing. Please view in Desktop widescreen
https://codesandbox.io/s/determined-bartik-2tftc?file=/pages/index.js
[Edit] : I just noticed the left side is hidden by the map now since the map is out of the flex flow. I'll keep the answer as an idea. If you can manipulate the architecture of the page, it's easy to fix.
Looks like applying :
position: fixed;
right: 0;
justify-content: end;
to the aside tag that contains the map and removing its top-0 class fix your problem. I see that you are using an external library to display the map so I don't know if there is a way to apply css to it since I can't edit the codesandbox sorry. You could just wrap it in a span with a class and target it with .my-class > aside in your css. But first check the documentation, they are probably exposing some classes for you to apply styles.
So I seemed to have solved this. Took a bit of work but I achieved the result I was looking for.
I added some root css here in globals.css file
:root {
--navigation-bar-offset: 90px;
--gp-placement-max-height: calc(100vh - var(--navigation-bar-offset, 80px));
}
I utilized these root class names to be used in index.js on the component parent div
<div className="w-full
sticky
top-[var(--navigation-bar-offset,80px)]
h-[var(--gp-placement-max-height,auto)]">
<MapBox searchResults={searchResults} />
</div>
I also found, that Mapbox was overriding my height from it's setViewport callback in Map.js. So I overrode Mapbox by adding this code in Map.js in the onViewportChange.
onViewportChange={nextViewport => setViewPort({ ...nextViewport, width: "100%", height: "100%" })}
I updated the Codesandbox to reflect these changes.
Also, if you resize the browser, it maintains height and width.
The below link is to a codesandbox for a project I am working on. The SideNav list items match the slides for navigation. The problem is that when I add an another different component (like other for example)to the return statement of slideshow.js, the list items are thrown off/incorrect/duplicated. I can't figure out why and am at the point of thinking its a react thing, or maybe a dependency I am using? console logging doesnt help me much so far.
ps: the list items are indexed by the "slide-title" class in AppContext.js.
https://codesandbox.io/s/test-r4ov3?file=/src/App.js
This Works Fine
<Fragment>
<Slide ref={slideRef} {...slideProperties} className="slide-container">
{SlideData.map((item, index) => (
<p key={index} className="slide-title">
{item.title}
</p>
))}
</Slide>
</Fragment>
This does not
<Fragment>
<Slide ref={slideRef} {...slideProperties} className="slide-container">
{SlideData.map((item, index) => (
<p key={index} className="slide-title">
{item.title}
</p>
))}
<div className="slide-title">Other</div><---ADDED
</Slide>
</Fragment>
BEFORE ADDING -LIST ITEMS MATCH
AFTER ADDING A COMPONENT- LIST ITEMS DUPLICATE?
This was a bug addressed in react-slideshow-image with version 3.4.7 as reported on the GitHub repo. There is also a workaround where you can use {[...mappeditems, SomeOtherComponent/>]} but it shouldn't be necessary now.
I'm using React router dom Link component. It is basically twitter's home feed. I want to be able to have two type of Links in one div component. One will be Link to go to user's profile and other one to go to post. I am currently getting warning and couldn't find solution for now. Here is the screenshot as reference:
I understand the issue here, my post Link is the parent element and I've added two user Link components inside of it as the user should be able to access post page when he clicks on anything inside of the post except user's profile photo and user's name. Is there any smarter way of achieving this and keeping links like this?
Code:
{posts?.map((post) => (
<Link
className={classes.link}
key={post.user.id}
to={`/posts/${post.id}`}
>
<div className={classes.post}>
<Link to={`/users/${post.user.id}`}>
<img
className={classes.profileImage}
src={DefaultLogo}
alt="default-profile"
/>
</Link>
<article className={classes.postDetails}>
<Link
className={classes.link}
to={`/users/${post.user.id}`}
>
<Typography
variant="subtitle1"
className={`${classes.postTitle} ${classes.content}`}
>
{post.user.name}
</Typography>
</Link>
<Typography
variant="subtitle1"
className={`${classes.postText} ${classes.content}`}
>
{post.body}
</Typography>
</article>
</div>
</Link>
))}
Yes, having anchor tags inside of another anchor tag is misleading a bad approach to doing things. But given your requirements you can make use of a basic button with react router dom history api.
A simple example:
import {Link, useHistory} from 'react-router-dom'
const App = () => {
const history = useHistory()
return (
<a
href='/user/1'
>
<h2>John doe</h2>
<div>here are some use information</div>
{/* Need to prevent the event bubbling */}
<Link role='link' to='/users/1/posts'>
User posts
</Link>
</div>
)
}
Right now my li tag has a mouseenter and mouseleave effect, but when I shrink my site down to mobile view, I want it to change to onClick instead.
So the code below shows my menu with the dropdown. Whenever I click on the hamburger menu in mobile view, it will trigger the active class on the <ul> and open up the mobile view. Then when I hover over the li tag it will display the dropdown menu.
Instead of it displaying when I hover, I need it to display when I click the ul tag only at the breakpoint of 960px.
<ul className={click ? 'nav-menu active' : 'nav-menu'}>
<li
className='nav-item'
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
<Link to='/' className='nav-links' onClick={() => setClick(false)}>
Home <i class='fas fa-caret-down' />
</Link>
{dropdown && <Dropdown />}
</li>
<li className='nav-item'>
<Link
to='/services'
className='nav-links'
onClick={() => setClick(false)}
>
Services
</Link>
</li>
</ul>
Is that something that is posssible to do? Or would I have to completely redo my code?
It most definitely is. And there are many options of how you could do it, these are some that come to my mind at first:
Option #1:
You could render 2 completely different things based on media query, something like this:
<div className="hidden-xs">
<ol onClick={() => {}}></ol>
</div>
<div className="hidden-lg">
<ol onMouseLeave={() => {}} onMouseEnter={() => {}}></ol>
</div>
Option #2:
You could disable certain functions based on current viewport
const onMouseEnter = () => {
if (window.width > something) {
return;
}
do something otherwise
}
const onClick = () => {
if (window.width < something) {
return;
}
do something otherwise
}
I would recommend taking a look at some of these articles & modules:
Medium post about media queries in React
react-media
react-responsive