Javascript 如何在映射中使用react useRef实现目标DOM
我正在寻找一个关于使用reactJavascript 如何在映射中使用react useRef实现目标DOM,javascript,reactjs,react-hooks,Javascript,Reactjs,React Hooks,我正在寻找一个关于使用reactuseRef()hook获取DOM元素数组的解决方案 例如: const Component = () => { // In `items`, I would like to get an array of DOM element let items = useRef(null); return <ul> {['left', 'right'].map((el, i) => <li key={i}
useRef()
hook获取DOM元素数组的解决方案
例如:
const Component = () =>
{
// In `items`, I would like to get an array of DOM element
let items = useRef(null);
return <ul>
{['left', 'right'].map((el, i) =>
<li key={i} ref={items} children={el} />
)}
</ul>
}
const组件=()=>
{
//在“items”中,我想得到一个DOM元素数组
let items=useRef(null);
返回
{['left','right'].map((el,i)=>
-
)}
}
我怎样才能做到这一点 如果您提前知道数组的长度(在您的示例中是这样做的),您只需创建一个ref数组,然后根据其索引分配每个ref:
const Component = () => {
const items = Array.from({length: 2}, a => useRef(null));
return (
<ul>
{['left', 'right'].map((el, i)) => (
<li key={el} ref={items[i]}>{el}</li>
)}
</ul>
)
}
const组件=()=>{
const items=Array.from({length:2},a=>useRef(null));
返回(
{['left','right'].map((el,i))=>(
- {el}
)}
)
}
useRef
与React的ref
只是部分相似(只是对象的结构,只有当前的字段)
useRef
hook的目标是在渲染之间存储一些数据,并且更改这些数据不会触发重新渲染(与useState
不同)
还有一个温和的提醒:最好避免在循环中初始化钩子,或者在的情况下初始化钩子。是的
考虑到这一点,我们:
通过useRef
我们通过createRef()
我们可以使用.current
符号来参考列表
const Component = () => {
let refs = useRef([React.createRef(), React.createRef()]);
useEffect(() => {
refs.current[0].current.focus()
}, []);
return (<ul>
{['left', 'right'].map((el, i) =>
<li key={i}><input ref={refs.current[i]} value={el} /></li>
)}
</ul>)
}
也不要在第一次渲染时尝试访问refs.current[0].current
-这将引发错误
说
返回(
{['left','right'].map((el,i)=>
-
{refs.current[i].current.value}
//无法读取未定义的属性'value'
)}
)
所以你要么把它当作
return (<ul>
{['left', 'right'].map((el, i) =>
<li key={i}>
<input ref={refs.current[i]} value={el} />
{refs.current[i].current && refs.current[i].current.value}</li> // cannot read property `value` of undefined
)}
</ul>)
返回(
{['left','right'].map((el,i)=>
-
{refs.current[i]。current&&refs.current[i]。current.value}
//无法读取未定义的属性'value'
)}
)
或者在useffect
hook中访问它。原因:ref
s是在元素渲染后绑定的,因此在渲染过程中第一次运行时它还没有初始化。我将稍微展开一下。对于性能优化(并避免潜在的奇怪错误),您可能更喜欢使用usemo
而不是useRef
。由于useMemo接受回调作为参数而不是值,React.createRef
将在第一次渲染后仅初始化一次。在回调中,您可以返回createRef
值的数组,并适当地使用该数组
初始化:
const refs= useMemo(
() => Array.from({ length: 3 }).map(() => createRef()),
[]
);
refs[i+1 % 3].current.focus();
此处的空数组(作为第二个参数)告诉React仅初始化引用一次。如果ref count发生更改,您可能需要将[x.length]
作为“一个deps数组”传递,并动态创建ref:array.from({length:x.length}).map(()=>createRef(),
用法:
const refs= useMemo(
() => Array.from({ length: 3 }).map(() => createRef()),
[]
);
refs[i+1 % 3].current.focus();
获取父引用并操纵子引用
const组件=()=>{
const ulRef=useRef(null);
useffect(()=>{
ulRef.current.children[0].focus();
}, []);
返回(
{['left','right'].map((el,i)=>(
-
))}
);
};代码>您可以将每个映射项分离到组件,而不是使用引用数组或类似的东西。将它们分开时,可以单独使用useRef
s:
const数据=[
{id:0,名称:“John”},
{id:1,名称:“Doe”}
];
//使用引用数组或类似的方法:
函数组件(){
const items=useRef(数组(DATA.length).fill(createRef());
返回(
{DATA.map((项目,i)=>(
-
{item.name}
))}
);
}
//将每个映射项分离到组件:
函数组件(){
返回(
{DATA.map((项目,i)=>(
))}
);
}
函数MapItemComponent({data}){
const itemRef=useRef();
return
{data.name}
}
我遇到了这样一个问题,读了Joer的答案,意识到您可以使用索引动态设置querySelector类,并只为整个父类设置一个引用。抱歉代码太多,但希望这对某人有所帮助:
import React, { useRef, useState } from 'react';
import { connectToDatabase } from "../util/mongodb";
export default function Top({ posts }) {
//const [count, setCount] = useState(1);
const wrapperRef = useRef(null);
const copyToClipboard = (index, areaNumber) => {
//
// HERE I AM USING A DYNAMIC CLASS FOR THE WRAPPER REF
// AND DYNAMIC QUERY SELECTOR, THEREBY ONLY NEEDING ONE REF ON THE TOP PARENT
const onePost = wrapperRef.current.querySelector(`.index_${index}`)
const oneLang = onePost.querySelectorAll('textarea')[areaNumber];
oneLang.select();
document.execCommand('copy');
};
var allPosts = posts.map((post, index) => {
var formattedDate = post.date.replace(/T/, ' \xa0\xa0\xa0').split(".")[0]
var englishHtml = post.en1 + post.en2 + post.en3 + post.en4 + post.en5;
var frenchHtml = post.fr1 + post.fr2 + post.fr3 + post.fr4 + post.fr5;
var germanHtml = post.de1 + post.de2 + post.de3 + post.de4 + post.de5;
return (
<div className={post.title} key={post._id}>
<h2>{formattedDate}</h2>
<h2>{index}</h2>
<div className={"wrapper index_" + index}>
<div className="one en">
<h3>Eng</h3>
<button onClick={() => {copyToClipboard(index, 0)}}>COPY</button>
<textarea value={englishHtml} readOnly></textarea>
</div>
<div className="one fr">
<h3>Fr</h3>
<button onClick={() => {copyToClipboard(index, 1)}}>COPY</button>
<textarea value={frenchHtml} readOnly></textarea>
</div>
<div className="one de">
<h3>De</h3>
<button onClick={() => {copyToClipboard(index, 2)}}>COPY</button>
<textarea value={germanHtml} readOnly></textarea>
</div>
</div>
</div>
)
})
return (
<div ref={wrapperRef}>
<h1>Latest delivery pages </h1>
<ul>
{allPosts}
</ul>
<style jsx global>{`
body{
margin: 0;
padding: 0;
}
h1{
padding-left: 40px;
color: grey;
font-family: system-ui;
font-variant: all-small-caps;
}
.one,.one textarea {
font-size: 5px;
height: 200px;
width: 300px;
max-width: 350px;
list-style-type:none;
padding-inline-start: 0px;
margin-right: 50px;
margin-bottom: 150px;
}
h2{
font-family: system-ui;
font-variant: all-small-caps;
}
.one h3 {
font-size: 25px;
margin-top: 0;
margin-bottom: 10px;
font-family: system-ui;
}
.one button{
width: 300px;
height: 40px;
margin-bottom: 10px;
}
@media screen and (min-width: 768px){
.wrapper{
display: flex;
flex-direction: row;
}
}
`}</style>
</div>
);
}
import React,{useRef,useState}来自“React”;
从“./util/mongodb”导入{connectToDatabase};
导出默认函数Top({posts}){
//const[count,setCount]=useState(1);
const wrapperRef=useRef(null);
const copyToClipboard=(索引,区域编号)=>{
//
//这里,我使用一个动态类作为包装器REF
//和动态查询选择器,因此只需要顶部父项上的一个REF
const onePost=wrapperRef.current.querySelector(`.index${index}`)
const oneLang=onePost.querySelectorAll('textarea')[areaNumber];
oneLang.select();
document.execCommand('copy');
};
var allPosts=posts.map((post,index)=>{
var formattedDate=post.date.replace(/T/,'\xa0\xa0\xa0')。拆分(“.”[0]
var englishHtml=post.en1+post.en2+post.en3+post.en4+post.en5;
var frenchHtml=post.fr1+post.fr2+post.fr3+post.fr4+post.fr5;
var germanHtml=post.de1+post.de2+post.de3+post.de4+post.de5;
返回(
{formattedDate}
{index}
英格
{copyToClipboard(索引,0)}>复制
Fr
{copyToClipboard(索引,1)}>复制
扩散系数
{copyToClipboard(索引,2)}>复制
)
})
返回(
最新交付页面
{allPosts}