1

my problem is ItemList animation, every time when i change an item - delete for example react renders and animates the whole itemList which is unnexpected behavior

Also i`d like my items to be animated when only delete and create items, im using react-spring library

But there is also an interesting thing. If i delete items from the lowest to up gradually it works as expected but if i delete elements from top to bottom the list of items rerenders and animates fully and i don`t unredstand why.

HomePage:


import PostForm from '../components/PostForm/PostForm';
import {MemoizedToDoList} from '../components/ToDoList/ToDoList';
import { useGetToDosQuery } from '../store/rtcApi';

const HomePage = () => {
  const data = useGetToDosQuery();

  return (
    <div>
      <div className="ToDoMain">
        <PostForm/>
        <MemoizedToDoList items={data.data? data.data.toDos.toDos:[]} isLoading={data.isLoading}/>
      </div>
    </div>
  )
}

export default HomePage;

ToDoList:

import React from 'react'

import { useGetToDosQuery } from '../../store/rtcApi';
import { useSelector } from 'react-redux';

import { useTransition } from 'react-spring';
import LoadingSpinner from "../LoadingSpinner/LoadingSpinner";
import ToDoItem from '../ToDoItem/ToDoItem'

import ToDoListCss from "./ToDoList.module.css";

const ToDoList = ({items, isLoading}) => {
  const {toDos} = useSelector(state => state.main);
  const {isAuth} = useSelector(state => state.auth);
  
  let toDosData = [];
  if(isAuth && items){
    toDosData = items;
  }else{
    toDosData = toDos;
  }

  const transition = useTransition(toDosData, {
    from: {x: -100, y:800, opacity: 0},
    enter: {x: 0, y:0, opacity: 1},
    leave: {x: 100, y: 800, opacity: 0},
    keys: item => item.id,
    trail: 300
  });

  if(isLoading)
   return <LoadingSpinner scaleSet={0.5}/>;
   
  return (
    <div className={ToDoListCss.toDoList}>
      {transition((style, item, key)=><ToDoItem style={style} item={item} key={key}/>)}
    </div>
  )
}

export const MemoizedToDoList = React.memo(ToDoList);

ToDoItem:

import React from 'react'

import { useDispatch, useSelector } from 'react-redux';
import { useRemoveToDoMutation } from "../../store/rtcApi";
import { removeToDo } from "../../store/slices/mainSlice";

import {useSpring, animated} from "react-spring";

import { BsPatchExclamationFill } from 'react-icons/bs';
import { RiDeleteBin2Line } from "react-icons/ri";
import ToDoItemCss from "./toDoItem.module.css";

const ToDoItem = ({item, style}) => {
  const dispatch = useDispatch();
  const {isAuth} = useSelector((state)=>state.auth);
  const [ removeUserToDo ] = useRemoveToDoMutation();

  const crossLineStyle = useSpring({
    to: { opacity: 1, width: "65%", transform:"rotate(8deg)" },
    from: { opacity: 0, width: "0%",  transform:"rotate(-20deg)" },
    reverse: !item.isComplete,
    config: { frequency: 0.1 }
  }); 

  const onRemoveItem = React.useCallback((item) => {
    if(isAuth){
      return removeUserToDo(item._id);
    }
    dispatch(removeToDo(item.id));
  }, [dispatch])

  return (
    <animated.div style={style} className={ToDoItemCss.toDoItem}>
      <animated.div style={crossLineStyle} className={ToDoItemCss.overCrossLineAnimated}></animated.div>
        <div className={ToDoItemCss.toDoItemText}>{item.title}</div>
        <div className={ToDoItemCss.todoItemIconGroup}>
            {item.isImportant && <div className={ToDoItemCss.todoItemImportantIcon}><BsPatchExclamationFill/></div>}
            <div onClick={()=>{onRemoveItem(item)}} className='todo-item_bin-icon'><RiDeleteBin2Line/></div>
        </div>
    </animated.div>
  )
}

export default ToDoItem;

I was trying to use memo and useCallBack but i think i don`t get how shoud i properly use it here with the RTC query and redux state.

Chunks of code from ToDoList:

  const transition = useTransition(toDosData, {
    from: {x: -100, y:800, opacity: 0},
    enter: {x: 0, y:0, opacity: 1},
    leave: {x: 100, y: 800, opacity: 0},
    keys: item => item.id,
    trail: 300
  });

  if(isLoading)
   return <LoadingSpinner scaleSet={0.5}/>;
   
  return (
    <div className={ToDoListCss.toDoList}>
      {transition((style, item, key)=><ToDoItem style={style} item={item} key={key}/>)}
    </div>
  )
export const MemoizedToDoList = React.memo(ToDoList);

and here i have used useCallback and i even dono why =))

ToDoItem

  const onRemoveItem = React.useCallback((item) => {
    if(isAuth){
      return removeUserToDo(item._id);
    }
    dispatch(removeToDo(item.id));
  }, [dispatch])

Here how it looks like

plaglamist
  • 43
  • 7

0 Answers0