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])