The mystery of the Accordion Effect: A Next.js/React.js issue where it slides up but refuses to

After implementing a custom accordion using next.js, I encountered an issue where the slide animation worked successfully when moving up and out upon clicking the button. However, when trying to move it back down into the content, it did not animate as expected, but instead directly pasted itself into the DOM.

Here are the attempts I made:

Below is the relevant JavaScript code:

import { useState, useEffect, useRef } from "react";
import styles from "NEXT.JS FROM A CSS FILE BELOW SHOWING THE CSS CODE";

const AsideCheckout = (props) => {
    const [accordionClick, setAccordionClick] = useState(false);
    const asideRef = useRef(null);

    const slideInAside = (e) => {
        setAccordionClick(!accordionClick);

        if (accordionClick !== false) {
            setTimeout(() => {
                asideRef.current.style.display = "none"; // works when the slide slides up and out i remove it with display none and the content below pushes itself up
            }, 400);
        }

        if (accordionClick !== true) {
            asideRef.current.style.display = "block"; // some how doesn't slide in from the top just pastes itself on the DOM THE PROBLEM
        }
    }

    useEffect(() => {
        asideRef.current.style.display = "none"; // initial launch making it display none
    }, []);

return (
<>
         <div className={styles.aside_accordion_button} onClick={slideInAside}>
            <button>CLICK</button>
         </div>
         <aside ref={asideRef} className={[styles.aside_checkout, accordionClick === true && styles.aside_show_checkout].join(" ")}>
           ... aside content etc
         </aside>
</>
)
}

The corresponding CSS code is as follows:


    .aside_checkout {
        grid-column: 1;
        grid-row: -2;
        overflow-y: hidden;
        transform: translateY(-100%);
        transition: transform 0.7s ease-in-out;
        /* display: none; commented out doing this in js */
    }

    .aside_show_checkout {
        transform: translateY(0);
        /* display: block; commented out doing this in js */
        transition: transform 0.7s ease-out;
    }

    .aside_accordion_button {
        grid-row: -3; // THIS IS THE BUTTON placed above the aside content with grid-row -3
        display: flex;
/* some of the properties emitted here CUZ not RELEVANT */
    }

Despite the smooth sliding motion for transform translateY(-100%), there seems to be an issue as it fails to slide back in smoothly using translateY(0); instead, it simply appears on the page without animating.

Answer №1

Solved the Issue Successfully

In order to improve the functionality of the slideInAside function, I implemented a setTimeout inside the if blocks. This was necessary to slightly slow down React and avoid issues with timing.


    const slideInAside = (e) => {
        setAccordionClick(!accordionClick);
     
        // Modifications made here
        if (accordionClick !== false) {
            asideRef.current.classList.remove(styles.aside_show_checkout);
            setTimeout(() => {
                asideRef.current.style.display = "none";
            }, 400);
        }

        if (accordionClick !== true) {
            asideRef.current.style.display = "block"; 
            setTimeout(() => {
                asideRef.current.classList.add(styles.aside_show_checkout); 
            }, 0);
        }
    }

Furthermore, I simplified the JSX by removing unnecessary code:

         <aside ref={asideRef} className={styles.aside_checkout}>
           ... aside content etc
         </aside>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Swipe JS: tap on the edge to view the next item

Currently utilizing Swipe JS to generate a full-screen image gallery and aiming to incorporate the functionality of clicking on the left or right edge to navigate between the previous and next slides. An attempt was made to create absolutely positioned a ...

Display user input within a modal dialogue box

I have a subscription form that requires users to enter their name and email address. After clicking on "Compete Now," a pop-up appears asking for workshop information and postal code. The form is functioning correctly as intended. However, I want the em ...

Storing data efficiently with Angular 2's local storage service

I am attempting to create a ToDoList using localstorage within a service. add.component.ts export class AddComponent implements OnInit { item: Item[]; constructor( private router: Router, private itemService: ItemService) { } ...

Why does starting up the Firebase emulators trigger the execution of one of my functions as well?

Upon running firebase emulators:start --only functions,firestore, the output I receive is as follows: $ firebase emulators:start --only functions,firestore i emulators: Starting emulators: functions, firestore ⚠ functions: The following emulators are ...

AngularJS is experiencing issues with the sorting filter 'orderBy'

I am experiencing an issue with sorting a table list that has three columns. I have implemented the ability to sort all columns in ascending and descending order. However, when I click on the -Tag to initiate the sorting process, I encounter the following ...

Generate a revised object from a function and return it to the caller

What is the most efficient way to update and return a new object from a function? I came up with this function: export const addItemToCart = (currentCart, item) => { const { name, ...otherProps } = item; // if the item is already in the cart if ...

I am trying to access the serial number data from an array of objects in ReactJS. Can anyone guide me

Is there a way to extract data from an array of objects, such as getting the serial number in ReactJS? In my current code snippet, I have an array called "number" with values [1, 2, 3]. My goal is to retrieve and display these numbers as a string like th ...

Looking to incorporate HTML and JavaScript to create two unique forms that can be submitted separately on a single webpage

If I can't find an answer, then I ask: There are two different forms on the page: one is the "ask for call" form (which appears on every page of the site) and the other is a simple "contact form" (specifically placed on the contact page). Both forms ...

Hiding and showing div elements using CSS, JavaScript, and PHP

Here is the current code snippet: <? while ($row1 = mysql_fetch_object($result1)) { echo '<a href="#" onclick="showhide("'.$row1->id.'");">Name</a>'; while ($row2 = mysql_fetch_object($result2)) { ...

JavaScript: Reorder an array to alternate between largest and smallest elements, starting with the largest

When working with an array of integers that need to be sorted in a specific order, such as: [1, -1, -3, 9, -2, -5, 4, 8,] We must rearrange them so that the largest number is followed by the smallest number, then the second largest number followed by the ...

Navigating and Organizing in Ionic Service Factory

Apologies for the beginner question. I am looking to incorporate filtering and sorting by name on my webpage. However, I have encountered two issues after attempting to implement this functionality using a factory in services.js: When typing a search ter ...

How can I avoid anti-aliasing in browsers when enlarging images?

Back in April 2012, Google's Chart Image API became deprecated but it was possible to generate QR codes using it. Although I know that I can adjust the size of the image produced by the API, I prefer to simply use CSS along with the width and height ...

Implement a jQuery slideshow with a full background image, aiming to set up a clickable link on the final image of the

Could someone please help me with a query I have regarding a background image slide show using jQuery code? I have set up a slide show with multiple images and would like to make the last image clickable. Is it possible to achieve this specific functionali ...

Display Text Only When Selected - Material-UI

Is there a way to display only the selected tab's text? I came across this code snippet in the MUI documentation that involves showing labels on selection. How can I achieve this effect, maybe by manipulating the state to change the color of the selec ...

How can I iterate through a directory containing files and extract the exported JavaScript object from each one?

In my current project using nodejs / nextjs, I have file system access and a folder containing multiple React files: content - blog-post-1.jsx - blog-post-2.jsx - blog-post-3.jsx The task at hand is to extract the frontmatter from each file. My init ...

Contact Form featuring a Text Area to complete the rest of the details

I am currently working on creating a contact form that has a design similar to the one shown below. However, I am facing challenges in getting the desired layout. I initially tried using flex-box but encountered issues with displaying the Text Area correct ...

Utilizing Highcharts pattern filling in a stacked column chart with Next.js

I've been working on integrating Highcharts into my Next.js project to create a column chart, but I'm facing an issue where the pattern-fill chart is not displaying. Removing the color: {} from the code below will make the chart visible. I'v ...

What is the method to retrieve results using 'return' from NeDB in vue.js?

Seeking assistance on retrieving data from NeDB within a method in a .vue file using electron-vue. Currently, I am aware that the data can be stored in a variable, but my preference is to fetch it using 'return' as I intend to utilize the result ...

printing not displaying colors

Is there a way to maintain the colors while printing my HTML page to PDF? <table class="table table-responsive table-striped"> <thead> <tr> <th>Elev</th> <th>Session n ...

Generate text input fields dynamically and store their values in an array using the Backbone.js framework

Is there a way to dynamically create text boxes based on a number input field with type='number'? Essentially, every time a user increments the number input, a new text box should be added to the backbone.js view. Additionally, when values are en ...