React新手关于useDrag绑定函数与扩展运算符的技术疑问
React拖拽代码疑问解答
先看你提供的代码片段:
import logo from './logo.svg'; import './App.css'; import {useState} from 'react'; import {useDrag} from 'react-use-gesture'; function App() { const [logoPos, setLogoPos] = useState({x:0, y:0}); const bindLogoPos = useDrag((params)=>{ setLogoPos({ x: params.offset[0], y: params.offset[1] }); }); return ( <div className="App"> <header className="App-header"> <div {...bindLogoPos()} style={{ position:'relative', top: logoPos.y, left: logoPos.x, }}> <img src={logo} className="App-logo" alt="logo" /> </div> ////////more...
问题1:为何bindLogoPos要以函数形式调用?
useDrag是react-use-gesture库提供的Hook,它返回的不是直接的事件处理对象,而是一个函数。这个函数被调用时,才会生成包含拖拽所需事件监听器(比如onMouseDown、onTouchStart)的对象。只有调用它,才能拿到这些需要绑定到DOM元素上的事件处理逻辑,让div具备拖拽能力。
问题2:扩展运算符...的作用是什么?
这里的...是ES6的对象扩展运算符,作用是把bindLogoPos()返回的对象里的所有键值对“展开”,直接作为div组件的props。比如bindLogoPos()返回的对象可能是{ onMouseDown: fn1, onTouchStart: fn2 },用...展开后,就相当于给div手动添加了onMouseDown={fn1}和onTouchStart={fn2},省去了逐个写事件绑定的麻烦。
问题3:{...bindLogoPos()}的含义、是否会无限调用、是否仅React可用?
- 含义:这是JSX中的对象展开语法,把
bindLogoPos()返回的事件处理对象的所有属性,作为props传递给div元素,让div拥有拖拽交互的能力。 - 不会造成无限调用:组件每次渲染时会执行一次
bindLogoPos(),但useDrag是Hook,只要其内部依赖(这里是传入的回调函数)不变,返回的函数调用后只会生成事件处理对象,不会触发setLogoPos或其他状态更新。只有当拖拽事件发生时,回调里的setLogoPos才会触发重新渲染,而重新渲染时调用bindLogoPos()也只是生成新的事件对象,不会引发新的状态更新,所以不会陷入无限循环。 - 并非仅React可用:对象扩展运算符是ES6的标准语法,在任何支持ES6的JS环境都能使用。而在JSX中用
{...对象}传递props的写法,不仅React支持,其他兼容JSX的框架(比如Preact、SolidJS)也同样支持,只是这个场景是结合React的Hook和拖拽库来用的。
内容的提问来源于stack exchange,提问作者Juyeon
相关产品推荐
相关产品推荐

