I have an array of items which I map in my UI:
let arr = [1, 2, 3, 4, 5, 6, 7... n]
Say I want to map each item as a JSX
paragraph BUT, I want to be able to change the order of each element within the array by calling a function swap
which changes the value of arr
(assume that arr
is stored in a redux slice
and automatically updates after calling function swap
.
For example, if I call the function swap(3, "up")
, then the item 3
will be swapped with the item 2
and the result will be: [1, 3, 2, 4, 5, 6, 7... n]
. Conversely, if I swap the other direction – down
, the item will swap with its successor.
I also have a delete
function which will remove the item altogether and all the items after it will get bumped up by one space: delete(4)
will result in [1, 2, 3, 5, 6, 7...n]
.
This logic is done, it all works and I have observed that the changes apply perfectly in the UI. The problem is that I need to somehow inform the user that this happened. For example, a transition or animation so that the action is not instant.
Here is what I have written:
const lectures = useSelector((state: RootState) => state.course.lectures)
/* lectures always is sorted by its positional index which changes with swap
(swapping two elements) and delete (deletes current and bumps up all its
successors) */
const delete = (lecture) => {
/* a dispatch to an action that will result in deleting an item from the lectures array */
}
const swap = (lecture, direction) => {
/* a dispatch to an action that will result in swapping the given lecture with its pred/succ depending on the direction. */
}
return (
<div>
{
lectures.map(lect => (
<span>
<h3>{lect.position_index}</h3>
<p>{lect.title}</p>
<button onClick={e => swap(lect, "up")}>UP</button>
<button onClick={e => swap(lect, "down")}>DOWN</button>
<button onClick={e => delete(lect)}>DELETE</button>
</span>
)
}
</div>
)
The changes apply but they are instantaneous. I want to add a transition of some sort – 200 or 300 milliseconds transition disappearing effect on delete and tbh anything for the swapping it doesn’t matter as long as the user knows that it happens.
I dont want the users to end up deleting the wrong lecture because they thought that their delete didn’t take effect.
I apologize for any misused terminology.
2
Answers
Okay, so it turns out that I cannot solve this with any libraries or tools - I had to implement my own solution as I expected.
The way I did this is by having two states in the parent component where I render my lectures -
deleting
andswapping
:Whenever I run a
delete
orswap
I basically set these states with thelecture id
and put thedispatch
in atimeout
:In my render I have basically the same code with a minor detail - conditioanl class name for when it is being deleted:
Finally, I have two
useEffects
which listen on changes todeleting
andswapping
states and update their state properly:I made it 2000ms assuming that it will not take more than 1500ms for the dispatch to resolve which currently takes up to 800ms on slow internet in production environment under stress conditions.
Try changing css styles with useState, not sure if it’s 100% what you’re looking for, but it definitely works.