react-spring中useTransition两种写法差异及失效原因咨询
React-Spring useTransition两种写法行为不一致问题
我刚学react-spring,参考官方文档用数组解构形式写useTransition(对应代码里的transitions变量),但没法正常工作:animated.div一直处于style="opacity: 0;"状态,完全显示不出来。后来查资料找到直接传配置对象的写法(对应代码里的transitionsTest变量),这种写法能正常运行。我搞不懂这两种写法为啥结果不一样,而且检查TypeScript类型也没发现差异。
测试代码
"use client"; import React, {memo, useEffect, useState} from 'react' import {animated, useTransition} from "@react-spring/web"; const Test = () => { useEffect(() => { changeItem() }, []) const [items, setItems] = useState<string[]>(["1", "2", "3", "4"]); const addItem = () => { const newItem = `Item ${items.length + 1}`; setItems([...items, newItem]); }; const removeItem = () => { if (items.length === 0) return; const newItems = items.slice(0, -1); setItems(newItems); }; const changeItem = () => { setItems(["1", "2", "3", "4"]) } // 无法正常工作的写法 const [transitions, api] = useTransition(items, () => ({ from: {opacity: 0}, enter: {opacity: 1}, leave: {opacity: 1}, config: {duration: 1000} })) // 正常工作的写法 const transitionsTest = useTransition(items, { from: {opacity: 0}, enter: {opacity: 1}, leave: {opacity: 1}, config: {duration: 1000} }); return ( <div> <div> <button onClick={addItem}>Add Item</button> <button onClick={removeItem}>Remove Item</button> <button onClick={changeItem}>Change Item</button> </div> <div> {transitions((style, item) => ( <animated.div style={style}>{item}</animated.div> ))} </div> <hr/> <div> {transitionsTest((style, item) => ( <animated.div style={style}>{item}</animated.div> ))} </div> </div> ); } export default memo(Test)
依赖信息
"dependencies": { "@next/mdx": "^13.4.4", "@react-spring/web": "^9.7.3", "@reduxjs/toolkit": "^1.9.7", "@types/node": "18.15.11", "@types/react": "^18.3.1", "@types/react-dom": "^18.3.0", "eslint": "8.38.0", "eslint-config-next": "^14.2.3", "immer": "^10.0.4", "next": "^14.2.3", "normalize.css": "^8.0.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-redux": "^8.1.3", "redux": "^4.2.1", "typescript": "^5.4.5", "use-immer": "^0.9.0" }, "devDependencies": { "sass": "^1.61.0" }
问题原因与解决方法
核心原因
数组解构的写法(返回[transitions, api])是react-spring的旧版API,在v9+版本中,它的参数顺序和新版API不同:
- 旧版API参数顺序:
useTransition(列表数据, 唯一键值函数, 配置函数/对象) - 你现在的写法把配置函数当成了「唯一键值函数」传入,导致react-spring无法正确识别列表项的变化,自然不会触发
enter动画,元素一直停留在from状态的opacity:0。
修复方案
方案1:补全旧版API的参数
如果要保留数组解构写法,需要传入正确的唯一键值函数:
const [transitions, api] = useTransition(items, item => item, // 用列表项本身作为唯一键(你的item是字符串,本身唯一) () => ({ from: {opacity: 0}, enter: {opacity: 1}, leave: {opacity: 1}, config: {duration: 1000} }) )
方案2:使用新版API(推荐)
直接传配置对象的写法是v9+推荐的新版API,更简洁不易出错,还可以在配置里指定键值:
const transitionsTest = useTransition(items, { keys: item => item, // 可选,若列表项本身唯一可省略,默认用索引 from: {opacity: 0}, enter: {opacity: 1}, leave: {opacity: 1}, config: {duration: 1000} });
内容的提问来源于stack exchange,提问作者SageJustus
相关产品推荐
相关产品推荐

