ReactJS轮播组件滑动动画实现求助:从零构建后无法添加动画
Hey there! Let's break this down step by step since you're new to React and animations—no fancy libraries required to get this working. First, let's fix a critical issue in your code that might be causing unexpected behavior, then add the slide animations.
Fix First: Remove setState in Render
First off, you've got a big issue here—never call this.setState() inside the render() method! Render should be a pure function that just returns JSX based on your state/props, no side effects. Those setState calls in your render are causing unnecessary re-renders and buggy behavior. Let's move that boundary logic into your changePositionNext and changePositionPrev methods instead.
Step 1: Update Position Logic
Let's fix the boundary checks so they work correctly even when your jobs list isn't a multiple of 3:
changePositionNext() { const { jobs, position } = this.state; const maxPosition = Math.max(0, jobs.length - 3); // Prevent negative positions if (jobs.length <= 3) return; // No need to slide if we have 3 or fewer cards const newPosition = position >= maxPosition ? 0 : position + 3; this.setState({ position: newPosition }); } changePositionPrev() { const { jobs, position } = this.state; const maxPosition = Math.max(0, jobs.length - 3); if (jobs.length <= 3) return; const newPosition = position <= 0 ? maxPosition : position - 3; this.setState({ position: newPosition }); }
This ensures we never set a position that would slice beyond the jobs array or go negative.
Step 2: Add Slide Animation with CSS
Since you're new to animations, let's use pure CSS transitions—they're straightforward and don't require any extra libraries. Here's how to adjust your JSX and SCSS:
Updated JSX Render
We'll add a slide_wrapper div around all your job cards. This wrapper will be the element we animate using transform: translateX:
render() { const { jobs, position } = this.state; // Calculate slide offset: each "page" of 3 cards shifts the wrapper by 1/3 of its width const slidePercentage = -(position / jobs.length) * 100; return ( <div className='main_container' id='job'> <BlocSection section_title={"Nos offres d'emploi"} section_intro={'Lorem ipsum dolor sit amet consectetur, adipisicing elit. Sequi alias iste ducimus tenetur saepe reprehenderit quasi reiciendis ab architecto.'} /> <div className='slider_container'> <div onClick={() => this.changePositionPrev()} className="arrow_container"> <img src={back} alt="Previous" className="arrow"/> </div> <div className="card_container"> {/* Wrapper to handle sliding animation */} <div className="slide_wrapper" style={{ transform: `translateX(${slidePercentage}%)` }} > {jobs.map(job => { const title = job.title.rendered; const description = job.acf.job_description; const lien = job.acf.job_linkedin_url; return( <JobCard key={title} title={title} description={description} lien={lien} /> ); })} </div> </div> <div onClick={() => this.changePositionNext()} className="arrow_container"> <img src={next} alt="Next" className="arrow"/> </div> </div> </div> ); }
Note: We're mapping all jobs instead of just selected now—this lets the wrapper contain every card, so the slide animation can smoothly move them in and out of view. The card_container will hide anything outside its bounds.
Updated SCSS
Add these styles to your Carousel.scss:
.card_container { overflow: hidden; // Hide cards outside the visible area width: 100%; } .slide_wrapper { display: flex; transition: transform 0.5s ease-in-out; // Smooth 0.5-second slide animation width: fit-content; // Let the wrapper grow to fit all cards } // Ensure each JobCard takes up exactly 1/3 of the container width .JobCard { flex: 0 0 calc(100% / 3); box-sizing: border-box; padding: 0 1rem; // Optional spacing between cards }
How This Works
- When
positionchanges, theslide_wrapper'stransform: translateXvalue updates automatically. - CSS handles the smooth animation of this change over 0.5 seconds (you can adjust the duration by changing
0.5s). - The
card_containerkeeps only 3 cards visible at a time, hiding the rest.
Why Your Earlier CSS Class Attempt Failed
Chances are, you were toggling classes without syncing them properly with React's state cycle. React needs to re-render when state changes to apply new styles—this method uses state directly to drive the animation, so it stays in sync with React's update process.
Key Takeaways for React Animations
- Never
setStatein render: It causes infinite loops and unpredictable behavior. - Start with CSS transitions: They're easier to learn than animation libraries when you're new to React.
- State drives UI changes: Let React state updates trigger your animations instead of trying to manually manipulate DOM classes.
You've already got the core carousel logic down—great work! The animation part just needed a small adjustment to how you structure the DOM and link state to styles.
内容的提问来源于stack exchange,提问作者Maëlle

