Multiple re-renders breaks CSS transition - reactjs

I have a draggable React pure component that pushes aside other draggables around it, triggering multiple re-renders.
However when the component is dragged too quickly (causing another re-render to occur before the CSS transition can finish animating) strange behaviours show up. The surrounding draggables will jump around unpredictably.
Everything works fine and transitions smoothly as long as I set a low enough transition time or drag the component slowly enough so that the transition finishes before the next re-render.
I'm using simple CSS transitions inside the component's style props, adding the transition property when the component is being actively dragged and removing it otherwise.
transition: "all 500ms ease"
Examples:
In both gifs, I'm dragging the leftmost panel towards the right. Each time there is a column swap, there is a re-render.
The top gif shows everything functioning as expected when dragging slowly and setting a low 100ms transition time.
In the bottom gif, I'm dragging too quickly causing the component to re-render before the first transition can complete. You can observe the leftmost panel moving out of frame towards the left side even though it's not being dragged.
Is there any way to delay re-rendering until the CSS animation is finished?
Is there another solution here that's typically applied for these situations?

Related

How to avoid a small delay in scrolling on react useEffect?

I have a component that will automatically keep the scroll position when the child of the overflow: scroll parent is grows/shrinks.
The code that keeps the scroll position works fine. However because I use useEffect to readjust the scroll position. I noticed that there are some delay causing the scroll position to seem like a glitch (scrolled really fast down and back to the initial position).
So I thought that this is caused by react will render the component first and then execute the scrollTop in the useEffect.
Is there any way to avoid this delay?
Maybe this question can be simplified to:
How can I render a react component with initial scroll position? (without delay or useEffect?)
It sounds like you may need: useLayoutEffect, it fires immediately after the DOM has been updated, but before the browser has had a chance to paint those changes:
useLayoutEffect is a version of useEffect that fires before the
browser repaints the screen.
useEffect on the other hand runs after the browser has painted, so if you have some code inside the useEffect which results in DOM changes, you may notice some flicker because of that.

Component using "Suspense" showing spinner on consequent loads (changing its height for a moment)

I'm rendering a number of items, where each individual item uses the same component:
This component internally uses Suspense:
<Suspense fallback={<Spinner />}>{children}</Suspense>
Whenever I click the paginator, a new set of items is rendered. Each of the items uses the same "Suspensed" component.
Problem: Each of the instances shows a fallback (spinner, loader) for a moment, and only then its content.
Since the fallback has constant height, this changes the height of the parent container, which makes the whole page jumping around:
I'm wondering how could I fix this? Basically, I'd like to avoid the new set of items to collapse due to showing the fallback. Sure, showing the fallback on initial load is fine, but I don't think the already loaded component (dynamically imported code) should show it on consequent pages.
I tried using React.startTransition, but that didn't help.
I also checked with components which are not lazily loaded, and everything works fine (parent height remains constant).
Thanks for help!
Update: I came up with a "poor man's fix":
wrapping children inside 2 divs
ResizeObserver monitoring the height of the inner div and setting the same height to the outer one, but in debounced fashion (100ms later)
Resources:
https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver
https://www.npmjs.com/package/use-debounce
Note: You'll probably need to mock ResizeObserver in your Jest tests: https://github.com/que-etc/resize-observer-polyfill/issues/50#issuecomment-488064120

Check if an element is in center in React

I'm implementing a carousel and I want to target the element at the center of the slider. So, I can make it pop a little.
How can I target this component? I have found ways to know if the element is inside the viewport or not but I want to know if it's horizontally centered.
Original Problem
Horizontal scroll and set state
Since you have no code my answer will be more theoretically how to do it.
So first off you should have a boolean state that you can toggle for the active state. This state should be controlled by the container. That way you can only activate one at a time.
Next you should get 2 values, the X scroll position of the container and the center point of the visible area of the gallery.
Then you can just calculate an offset on mount and then X scroll of the gallery.
So in theory it starts at 0 and your container is 500px you know that the active slide is at the 250px mark so you can calculate that with the position of the slide, it should be the last slide that passed that point. then just recalculate this value on scroll. (maybe throttle)
Possibly able to use react-hook-inview
I've used this react hook before on the Y axis. I'm not 100% sure that it works on the X scroll. But it can be a great way to trigger a state change on each of the slides. The only issue is that you'll be adding a event listener to each of your slides (possible performance hit).
You can see that lib here
This one lets each slide control it's own inView state.

Well behaving custom switch or slider components nested in scrollable containers

Some time ago I noticed that nested scrollable containers behave nice - for example several containers scrollable in their X-axis nested in a container that is scrollable in its Y-axis - and decided to take advantage of this by creating a custum composite swich component based on that and snapToGrid.
However this never worked out nicely since snapToGrid had its problems.
When I talk about well-behaviour of nested scrollable components I mean you can tap on a nested scrollable component and it will just work well being able to scroll either the component itself or its also scrollable parent in the other axis.
What would I need to do in a custom scrollable component to achieve the same well-behaviour like it works with nested containers?
What I'd require of such a component - for example a switch - was beeing able to switch it horizontally while, once it notices that horizontal dragging threshold is reached, and not to affect its parent containers vertical scrolling then. The other case where, after a certain threshold of vertival scrolling in the parent component, it locks to vertically scrolling the parent container should already work, right?
By the way - with the out-of-the-box CN1 OnOffSwitch this does not work. When they are placed in containers nested in a container with BoxLayout.Y the this way represented list cannot be scrolled when tapping one of the OnOffSwitches and dragging vertically.
Events in Codename One are delivered from the system in the following order:
The parent Form - e.g. you can override the pointer* callbacks
Form listeners - e.g. appPointer*Listener on Form
Builtin scroll if you are scrolling
Focused component
I'm assuming you used focus to grab events which essentially blocks child components from grabbing the events.
If you did such a thing you need to deliver the events to the child yourself using the pointer callbacks on the given component. You can find the component at a given x/y coordinate using getComponentAt(x, y).

Animation with display flex

When I open the item-accordion I have used the animation .But the item-accordion has the image that is wrap in the multiple row using display flex property of the CSS3. Whenever I open the accordion the extra content is displayed on the right during transition.So can anyone suggest what can be done to solve it?And this happens when width of the content is small
Another problem is i have used the animate-repeat animation to delete the item.But when i open the item-accordion the animation is applied to them also hence animating the image as a list.
.list .item-accordion {
-webkit-transition:0.09s all linear ;
transition: 0.09s all linear;
}
This is the animation I am using.
The demo of the code is over here:
http://plnkr.co/edit/FnQVCYrSGOlpk5wNxAZ6?p=preview
I have had similar issues when having to meet complex animation requirements. I have used greensock for more complex animations but that doesn't seem to be needed here. The general concept is that you are going to want to animate something but change/alter the properties before and after the animation has completed. You are going to have to be using a few callback promises to run additional animation after the first part of the animation has completed or do some manual calculations and adjust properties before starting or ending.
Angular Animate
Ionic Animate
It seems like ionic is allowing for onStart and onEnd callbacks. I would hide or force certain properties onStart and reset them onEnd so that you can get around what you are trying to work with. If you are not wanting to work with a fixed width or height you are going to have to grab window/screen size and so some basic calculations based on that. So you would get your window size set the size based on the window for the animation then reset back to auto when completed.

Resources