如何在worklet函数中调用React useState的setter方法?
如何在worklet函数中调用React useState的setter方法?
嘿,我来帮你搞定这个问题!你遇到的核心问题是runOnJS的使用方式不对——它的正确用法是先传入要执行的JS函数,再传递该函数需要的参数,而不是直接把整个函数逻辑包裹进去。
问题根源
你之前在runOnJS里直接写了状态更新的逻辑,这个回调其实还是运行在worklet的UI线程上下文里,并没有正确切换到React的JS主线程,所以状态更新没生效,对应的console.log也可能看不到预期的输出。
修正步骤
- 把状态更新逻辑抽成独立的JS函数:因为worklet不能直接操作React状态,必须通过
runOnJS桥接回JS主线程执行纯JS逻辑。 - 正确调用
runOnJS:先传入你定义的状态更新函数,再传递该函数需要的参数(比如这里的newItem)。
修正后的完整代码片段
import {runOnJS} from 'react-native-reanimated'; // 单独定义JS线程的状态更新函数 const addDuctItem = (newItem) => { setDuctItems((prevDuctItems) => { const updatedDuctItems = [...prevDuctItems, newItem]; console.log('Updated ductItems:', updatedDuctItems); return updatedDuctItems; }); }; const handleDragEnd: DndProviderProps['onDragEnd'] = ({active, over}) => { 'worklet'; if (over) { console.log('onDragEnd', {active, over}); console.log(active); const newItem = { partName: `${active.id.split('-')[0]}`, }; // 正确调用runOnJS:先传函数,再传参数 runOnJS(addDuctItem)(newItem); dynamicData.value = { over: over, }; } }; return ( <GestureHandlerRootView> <View style={styles.container}> <DndProvider onDragEnd={handleDragEnd} > <Droppable id="drop" style={styles.dropBox}> <Text>DROP</Text> </Droppable> <View style={styles.partsContainer}> <Text>{JSON.stringify(ductItems)}</Text> {ductItems.map((item, index) => ( <DraggableCustomComponent style={styles.partItem} id={`${item.partName}-${index}-key`} key={`${item.partName}-${index}-key`} partType={item.partName} data={dynamicData} /> ))} </View> </DndProvider> </View> </GestureHandlerRootView> );
额外注意事项
- 确保
runOnJS从react-native-reanimated正确导入,版本也要适配(v2+的用法都是这样)。 - worklet函数里不能直接访问React的状态或setter,所有需要操作React状态的逻辑都要放在JS线程的函数里,通过
runOnJS调用。 - 如果你的参数(比如
newItem)是在worklet里生成的,一定要作为参数传递给JS函数,因为worklet和JS环境的作用域是完全隔离的。 - React状态更新是异步的,如果你在调用
setDuctItems后立刻读取ductItems,拿到的还是旧值,要依赖setDuctItems的回调或者useEffect监听ductItems的变化来处理后续逻辑。
备注:内容来源于stack exchange,提问作者Brian Var
相关产品推荐
相关产品推荐

