React新文档切记不要滥用Ref_React
时间:2022-07-19 09:15 来源:网络 作者:素浅 点击:次
引言
显然,正常航行时是不需要逃生舱的,只有在遇到危险时会用到。
如果开发者过多依赖这两个
在React新文档:不要滥用effect哦中我们谈到
今天,我们来聊聊
为什么是逃生舱?
先思考一个问题:为什么 这是因为二者操作的都是脱离React控制的因素。
同样,使DOM聚焦需要调用
虽然他们是脱离React控制的因素,但为了保证应用的健壮,
失控的Ref
对于 首先来看不失控的情况:
这些情况下,虽然我们操作了 但是下面的情况:
同样是操作 举个例子,下面是React文档中的例子:
按钮1点击后会插入/移除 P节点,按钮2点击后会调用 export default function Counter() { const [show, setShow] = useState(true); const ref = useRef(null); return ( <div> <button onClick={() => { setShow(!show); }}> Toggle with setState </button> <button onClick={() => { ref.current.remove(); }}> Remove from the DOM </button> {show && <p ref={ref}>Hello world</p>} </div> ); }
按钮1通过
按钮2直接操作 如果这两种移除P节点的方式混用,那么先点击按钮1再点击按钮2就会报错:
这就是使用Ref操作DOM造成的失控情况导致的。
如何限制失控
现在问题来了,既然叫失控了,那就是
在
低阶组件指那些基于DOM封装的组件,比如下面的组件,直接基于 function MyInput(props) { return <input {...props} />; }
在低阶组件中,是可以直接将 function MyInput(props) { const ref = useRef(null); return <input ref={ref} {...props} />; }
高阶组件指那些基于低阶组件封装的组件,比如下面的 function Form() { return ( <> <MyInput/> </> ) }
高阶组件无法直接将
以文档中的示例为例,如果我们想在 function MyInput(props) { return <input {...props} />; } function Form() { const inputRef = useRef(null); function handleClick() { inputRef.current.focus(); } return ( <> <MyInput ref={inputRef} /> <button onClick={handleClick}> input聚焦 </button> </> ); } 点击后,会报错:
这是因为在 究其原因,就是上面说的为了将ref失控的范围控制在单个组件内,React默认情况下不支持跨组件传递ref。
人为取消限制
如果一定要取消这个限制,可以使用 const MyInput = forwardRef((props, ref) => { return <input {...props} ref={ref} />; }); function Form() { const inputRef = useRef(null); function handleClick() { inputRef.current.focus(); } return ( <> <MyInput ref={inputRef} /> <button onClick={handleClick}> Focus the input </button> </> ); }
使用
在例子中,我们将
在实践中,一些同学可能觉得
但从ref失控的角度看,
同时,有了
useImperativeHandle
除了限制跨组件传递ref外,还有一种防止ref失控的措施,那就是 既然ref失控是由于使用了不该被使用的DOM方法(比如appendChild),那我可以限制ref中只存在可以被使用的方法。
用 const MyInput = forwardRef((props, ref) => { const realInputRef = useRef(null); useImperativeHandle(ref, () => ({ focus() { realInputRef.current.focus(); }, })); return <input {...props} ref={realInputRef} />; });
现在, { focus() { realInputRef.current.focus(); }, } 就杜绝了开发者通过ref取到DOM后,执行不该被使用的API,出现ref失控的情况。
总结
正常情况,
为了防止错用/滥用导致
为了破除这种限制,可以使用
为了减少 以上就是React新文档切记不要滥用Ref的详细内容,更多关于React新文档Ref的资料请关注其它相关文章! |