1 回答

TA貢獻1818條經驗 獲得超8個贊
問題
React.createRef
實際上只在基于類的組件中有效。如果在功能組件主體中使用,則將在每個渲染周期重新創建引用。不要使用 DOM 查詢選擇器將
onClick
偵聽器附加到 DOM 元素。這些存在于外部反應,您需要記住清理它們(即刪除它們),這樣就不會出現內存泄漏。使用 React 的onClick
prop。映射后,您將相同的
selectedElements
引用附加到每個元素,因此最后一組是您的 UI 獲取的元素。
解決方案
在功能組件主體中使用
React.useRef
來存儲反應引用數組,以附加到要滾動到視圖中的每個元素。scrollSmoothHandler
將直接附加到每個span
的onClick
支柱上。將 1. 中創建的引用數組中的每個引用附加到要滾動到的每個映射字段集。
代碼
import React, { createRef, useRef } from "react";
import { render } from "react-dom";
const App = () => {
const selectedElements = [
"Item One",
"Item Two",
"Item Three",
"Item Four",
"Item Five"
];
// React ref to store array of refs
const scrollRefs = useRef([]);
// Populate scrollable refs, only create them once
// if the selectedElements array length is expected to change there is a workaround
scrollRefs.current = [...Array(selectedElements.length).keys()].map(
(_, i) => scrollRefs.current[i] ?? createRef()
);
// Curried handler to take index and return click handler
const scrollSmoothHandler = (index) => () => {
scrollRefs.current[index].current.scrollIntoView({ behavior: "smooth" });
};
return (
<div>
<div id="container">
<div className="_2iA8p44d0WZ">
{selectedElements.map((el, i) => (
<span
className="chip _7ahQImy"
onClick={scrollSmoothHandler(i)} // <-- pass index to curried handler
>
{el}
</span>
))}
<input
type="text"
className="searchBox"
id="search_input"
placeholder="Select"
autoComplete="off"
value=""
/>
</div>
</div>
<div>
{selectedElements.map((item, i) => (
<div
key={i}
className="selected-element"
ref={scrollRefs.current[i]} // <-- pass scroll ref @ index i
>
<fieldset>
<legend>{item}</legend>
</fieldset>
</div>
))}
</div>
</div>
);
};
解決方案#2
由于您無法更新div
with中的任何元素id="container"
,并且所有onClick
處理程序都需要通過查詢 DOM 來附加,因此您仍然可以使用柯里化scrollSmoothHandler
回調并將索引包含在范圍內。您需要一個鉤子來在初始渲染后useEffect
查詢 DOM ,以便安裝跨度,并需要一個鉤子來存儲“已加載”狀態。該狀態是觸發重新渲染并重新包含在回調中所必需的。useState
scrollRefs
scrollSmoothHandler
const App = () => {
const selectedElements = [
"Item One",
"Item Two",
"Item Three",
"Item Four",
"Item Five"
];
const [loaded, setLoaded] = useState(false);
const scrollRefs = useRef([]);
const scrollSmoothHandler = (index) => () => {
scrollRefs.current[index].current.scrollIntoView({ behavior: "smooth" });
};
useEffect(() => {
const chipsArray = document.querySelectorAll("#container > div > .chip");
if (!loaded) {
scrollRefs.current = [...Array(chipsArray.length).keys()].map(
(_, i) => scrollRefs.current[i] ?? createRef()
);
chipsArray.forEach((elem, index) => {
elem.addEventListener("click", scrollSmoothHandler(index));
});
setLoaded(true);
}
}, [loaded]);
return (
<div>
<div id="container">
<div className="_2iA8p44d0WZ">
<span className="chip _7ahQImy">Item One</span>
<span className="chip _7ahQImy">Item Two</span>
<span className="chip _7ahQImy">Item Three</span>
<span className="chip _7ahQImy">Item Four</span>
<span className="chip _7ahQImy">Item Five</span>
<input
type="text"
className="searchBox"
id="search_input"
placeholder="Select"
autoComplete="off"
value=""
/>
</div>
</div>
<div>
{selectedElements.map((item, i) => (
<div key={i} className="selected-element" ref={scrollRefs.current[i]}>
<fieldset>
<legend>{item}</legend>
</fieldset>
</div>
))}
</div>
</div>
);
};
添加回答
舉報