如何在 react-spring 中使用 useTransition 为列表过滤设置动画
How to animate the filtering of a list using useTransition in react-spring
我正在尝试在使用 react-spring
v9.x 中的新 useTransition
hook changes 进行过滤时为列表的过渡设置动画,以便在过滤列表项时将剩余的项目移动到新位置。
到目前为止,我已经设法让列表中的组件淡入和淡出,但其余组件只是在淡出动画完成后立即跳转到它们的新位置。我没能改变这个。
如何为其余组件设置动画以顺利移动到它们的新位置?
这是当前代码的code sandbox link。
如果在搜索栏中输入'p',可以看到名称为Plum
的组件在短暂的延迟后跳起来,您可以看到最清晰的跳跃效果。
App.js
import { useState } from "react";
import { useSpring, useTransition, animated } from "react-spring";
export default function App() {
const [items, setItems] = useState([
{ name: "Apple", key: 1 },
{ name: "Banana", key: 2 },
{ name: "Orange", key: 3 },
{ name: "Kiwifruit", key: 4 },
{ name: "Plum", key: 5 }
]);
const [searchText, setSearchText] = useState("");
const filteredItems = items.filter((item) =>
item.name.toLowerCase().includes(searchText.toLowerCase())
);
const transition = useTransition(filteredItems, {
from: { opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 0 }
});
const fadeInListItems = transition((style, item) => {
return (
<animated.div style={style}>
<Item data={item} />
</animated.div>
);
});
const handleSearchBarChange = ({ target }) => setSearchText(target.value);
return (
<div className="App">
<h2>Click on an item to toggle the border colour.</h2>
<SearchBar onChange={handleSearchBarChange} value={searchText} />
{fadeInListItems}
</div>
);
}
const SearchBar = (props) => {
return (
<>
<label>Search Bar: </label>
<input onChange={props.onChange} value={props.searchText} type="text" />
</>
);
};
const Item = (props) => {
const [isClicked, setIsClicked] = useState(false);
const [styles, api] = useSpring(() => ({
border: "2px solid black",
margin: "5px",
borderRadius: "25px",
boxShadow: "2px 2px black",
backgroundColor: "white",
color: "black"
}));
const handleClick = (e) => {
api.start({
backgroundColor: isClicked ? "white" : "red",
color: isClicked ? "black" : "white"
});
setIsClicked((prev) => !prev);
};
return (
<animated.div style={styles} onClick={handleClick} key={props.data.key}>
{props.data.name}
</animated.div>
);
};
您可以通过使用 max-height
(以及淡入淡出)隐藏过滤后的元素来实现该效果。这样,项目将“折叠”而不是仅仅消失,因此剩余的元素将“滑动”起来。
转变
const transition = useTransition(filteredItems, {
from: { opacity: 0, marginTop: 5 },
enter: { opacity: 1, maxHeight: 50, marginTop: 5 },
leave: { opacity: 0, maxHeight: 0, marginTop: 0 }
});
我还添加了 overflow: hidden
以完成 maxHeight
的效果并删除了 Item
的 margin: 5px
因为我在过渡 --definition 中添加了边距。
const [styles, api] = useSpring(() => ({
border: "2px solid black",
-- margin: "5px",
borderRadius: "25px",
boxShadow: "2px 2px black",
backgroundColor: "white",
color: "black",
++ overflow: "hidden",
}));
https://codesandbox.io/s/react-spring-demo-change-border-colour-on-click-forked-7fdkl
我正在尝试在使用 react-spring
v9.x 中的新 useTransition
hook changes 进行过滤时为列表的过渡设置动画,以便在过滤列表项时将剩余的项目移动到新位置。
到目前为止,我已经设法让列表中的组件淡入和淡出,但其余组件只是在淡出动画完成后立即跳转到它们的新位置。我没能改变这个。
如何为其余组件设置动画以顺利移动到它们的新位置?
这是当前代码的code sandbox link。
如果在搜索栏中输入'p',可以看到名称为Plum
的组件在短暂的延迟后跳起来,您可以看到最清晰的跳跃效果。
App.js
import { useState } from "react";
import { useSpring, useTransition, animated } from "react-spring";
export default function App() {
const [items, setItems] = useState([
{ name: "Apple", key: 1 },
{ name: "Banana", key: 2 },
{ name: "Orange", key: 3 },
{ name: "Kiwifruit", key: 4 },
{ name: "Plum", key: 5 }
]);
const [searchText, setSearchText] = useState("");
const filteredItems = items.filter((item) =>
item.name.toLowerCase().includes(searchText.toLowerCase())
);
const transition = useTransition(filteredItems, {
from: { opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 0 }
});
const fadeInListItems = transition((style, item) => {
return (
<animated.div style={style}>
<Item data={item} />
</animated.div>
);
});
const handleSearchBarChange = ({ target }) => setSearchText(target.value);
return (
<div className="App">
<h2>Click on an item to toggle the border colour.</h2>
<SearchBar onChange={handleSearchBarChange} value={searchText} />
{fadeInListItems}
</div>
);
}
const SearchBar = (props) => {
return (
<>
<label>Search Bar: </label>
<input onChange={props.onChange} value={props.searchText} type="text" />
</>
);
};
const Item = (props) => {
const [isClicked, setIsClicked] = useState(false);
const [styles, api] = useSpring(() => ({
border: "2px solid black",
margin: "5px",
borderRadius: "25px",
boxShadow: "2px 2px black",
backgroundColor: "white",
color: "black"
}));
const handleClick = (e) => {
api.start({
backgroundColor: isClicked ? "white" : "red",
color: isClicked ? "black" : "white"
});
setIsClicked((prev) => !prev);
};
return (
<animated.div style={styles} onClick={handleClick} key={props.data.key}>
{props.data.name}
</animated.div>
);
};
您可以通过使用 max-height
(以及淡入淡出)隐藏过滤后的元素来实现该效果。这样,项目将“折叠”而不是仅仅消失,因此剩余的元素将“滑动”起来。
转变
const transition = useTransition(filteredItems, {
from: { opacity: 0, marginTop: 5 },
enter: { opacity: 1, maxHeight: 50, marginTop: 5 },
leave: { opacity: 0, maxHeight: 0, marginTop: 0 }
});
我还添加了 overflow: hidden
以完成 maxHeight
的效果并删除了 Item
的 margin: 5px
因为我在过渡 --definition 中添加了边距。
const [styles, api] = useSpring(() => ({
border: "2px solid black",
-- margin: "5px",
borderRadius: "25px",
boxShadow: "2px 2px black",
backgroundColor: "white",
color: "black",
++ overflow: "hidden",
}));
https://codesandbox.io/s/react-spring-demo-change-border-colour-on-click-forked-7fdkl