React-hooks系列 useRef 使用 二
前言
有时你可能需要访问由React的DOM元素,例如,以聚焦、滚动到它,或测量它的大小和位置。在React中没有内置的方法来完成这些事情,因此需要Refs去操作DOM节点。
目录
一、 怎么挂载Refs到Dom结点
二、如何在遍历JSX时对每个item加ref
三、 如何访问别的组件的Refs
四、 Refs操作Dom的注意事项
怎么挂载Refs到Dom结点
- 先引入
useRef
import { useRef } from 'react';
- 调用useRef,
const myRef = useRef(0);
3.绑定Refs到对应的html
<div ref={myRef}>
4.使用浏览器的api
// You can use any browser APIs, for example:
myRef.current.scrollIntoView();
二、如何在遍历JSX时对每个item加ref
如果我们想要遍历中设置ref。
<ul>
{items.map((item) => {
// Doesn't work!
const myRef = useRef(null);
return <li ref={myRef} />;
})}
</ul>
以上方法是不正确的,原因是useRef是hook,应该放在顶层,但是如果放在顶层,myRef就会一直被覆盖。下面介绍两种解决方案。
1、把 ref绑定在遍历jsx的父元素,再对子元素操作。
但是,如果DOM结构发生变化,这种方法会变得很脆弱,可能会出现遍历中断。
<ul ref={myRef}>
{items.map((item) => {
const myRef = useRef(null);
return <li/>;
})}
</ul>
//example use it
listRef.current.lastChild.scrollIntoView
2、用map去记录每个list的每个ref
<ul >
{items.map((item) => {
return <li
key={id}
ref={(node) => {
myRef.current = new Map();
const map = myRef.current;
if (node) {
map.set(id, node);
} else {
map.delete(id);
}
}}
/>;
})}
</ul>
//example use it
const map = myRef.current;
const node = map.get(id);
node.scrollIntoView();
三、 如何访问别的组件的Refs
import { useRef } from 'react';
function MyInput(props) {
return <input {...props} />;
}
export default function MyForm() {
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus();
}
return (
<>
<MyInput ref={inputRef} />
<button onClick={handleClick}>
Focus the input
</button>
</>
);
}
上面这段代码,在控制台打开会提示报错信息。
要想在MyInput组件中使用父组件的ref,则需要再MyInput引入forwardRef
const MyInput = forwardRef((props, ref) => {
return <input {...props} ref={ref} />;
});
四、 Refs操作Dom的注意事项
Refs是一个逃生口。你应该只在必须走出React时才使用它们。常见的例子包括聚焦问题、滚动位置或调用React不公开的浏览器api。
如果你只是操作聚焦和滚动这样的非破坏性操作,你不会遇到任何问题。但是,如果你尝试手动修改DOM,您可能会面临与React自身操作最后导致冲突的风险。
至此关于react的Refs内容赞告一段落。