滚动到反应视图中

我正在制作一个简单的反应应用程序,其中有两个不同的div's..


具有选择输入和选定列表的一个,


  <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>

另一个会将所选选项列出为fieldset,


  <div>

    {selectedElements.map((item, i) => (

      <div key={i} className="selected-element" ref={scrollDiv}>

        <fieldset>

          <legend>{item}</legend>

        </fieldset>

      </div>

    ))}

  </div>

基于这个解决方案,我已添加createRef到所选元素,例如,


<div key={i} className="selected-element" ref={scrollDiv}>

</div>

然后我采用 Javascript 查询方法来获取 DOM 元素,例如,


  const chipsArray = document.querySelectorAll("#container > div > .chip");

向所有元素添加了单击事件侦听器,例如,


  chipsArray.forEach((elem, index) => {

    elem.addEventListener("click", scrollSmoothHandler);

  });

然后scrollSmoothHandler就像,


const scrollDiv = createRef();


  const scrollSmoothHandler = () => {

    console.log(scrollDiv.current);

    if (scrollDiv.current) {

      scrollDiv.current.scrollIntoView({ behavior: "smooth" });

    }

  };

但这并没有按预期工作。


森栏
浏览 115回答 1
1回答

弑天下

问题React.createRef实际上只在基于类的组件中有效。如果在功能组件主体中使用,则将在每个渲染周期重新创建引用。不要使用 DOM 查询选择器将onClick侦听器附加到 DOM 元素。这些存在于外部反应,您需要记住清理它们(即删除它们),这样就不会出现内存泄漏。使用 React 的onClickprop。映射后,您将相同的selectedElements引用附加到每个元素,因此最后一组是您的 UI 获取的元素。解决方案在功能组件主体中使用React.useRef来存储反应引用数组,以附加到要滚动到视图中的每个元素。scrollSmoothHandler将直接附加到每个span的onClick支柱上。将 1. 中创建的引用数组中的每个引用附加到要滚动到的每个映射字段集。代码import React, { createRef, useRef } from "react";import { render } from "react-dom";const App = () => {&nbsp; const selectedElements = [&nbsp; &nbsp; "Item One",&nbsp; &nbsp; "Item Two",&nbsp; &nbsp; "Item Three",&nbsp; &nbsp; "Item Four",&nbsp; &nbsp; "Item Five"&nbsp; ];&nbsp; // React ref to store array of refs&nbsp; const scrollRefs = useRef([]);&nbsp; // Populate scrollable refs, only create them once&nbsp; // if the selectedElements array length is expected to change there is a workaround&nbsp; scrollRefs.current = [...Array(selectedElements.length).keys()].map(&nbsp; &nbsp; (_, i) => scrollRefs.current[i] ?? createRef()&nbsp; );&nbsp; // Curried handler to take index and return click handler&nbsp; const scrollSmoothHandler = (index) => () => {&nbsp; &nbsp; scrollRefs.current[index].current.scrollIntoView({ behavior: "smooth" });&nbsp; };&nbsp; return (&nbsp; &nbsp; <div>&nbsp; &nbsp; &nbsp; <div id="container">&nbsp; &nbsp; &nbsp; &nbsp; <div className="_2iA8p44d0WZ">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {selectedElements.map((el, i) => (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; className="chip _7ahQImy"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onClick={scrollSmoothHandler(i)} // <-- pass index to curried handler&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {el}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ))}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <input&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type="text"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; className="searchBox"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id="search_input"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder="Select"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; autoComplete="off"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value=""&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; />&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; <div>&nbsp; &nbsp; &nbsp; &nbsp; {selectedElements.map((item, i) => (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; key={i}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; className="selected-element"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ref={scrollRefs.current[i]} // <-- pass scroll ref @ index i&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; >&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <fieldset>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <legend>{item}</legend>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </fieldset>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; ))}&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; );};解决方案#2由于您无法更新divwith中的任何元素id="container",并且所有onClick处理程序都需要通过查询 DOM 来附加,因此您仍然可以使用柯里化scrollSmoothHandler回调并将索引包含在范围内。您需要一个钩子来在初始渲染后useEffect查询 DOM&nbsp;,以便安装跨度,并需要一个钩子来存储“已加载”状态。该状态是触发重新渲染并重新包含在回调中所必需的。useStatescrollRefsscrollSmoothHandlerconst App = () => {&nbsp; const selectedElements = [&nbsp; &nbsp; "Item One",&nbsp; &nbsp; "Item Two",&nbsp; &nbsp; "Item Three",&nbsp; &nbsp; "Item Four",&nbsp; &nbsp; "Item Five"&nbsp; ];&nbsp; const [loaded, setLoaded] = useState(false);&nbsp; const scrollRefs = useRef([]);&nbsp; const scrollSmoothHandler = (index) => () => {&nbsp; &nbsp; scrollRefs.current[index].current.scrollIntoView({ behavior: "smooth" });&nbsp; };&nbsp; useEffect(() => {&nbsp; &nbsp; const chipsArray = document.querySelectorAll("#container > div > .chip");&nbsp; &nbsp; if (!loaded) {&nbsp; &nbsp; &nbsp; scrollRefs.current = [...Array(chipsArray.length).keys()].map(&nbsp; &nbsp; &nbsp; &nbsp; (_, i) => scrollRefs.current[i] ?? createRef()&nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; &nbsp; chipsArray.forEach((elem, index) => {&nbsp; &nbsp; &nbsp; &nbsp; elem.addEventListener("click", scrollSmoothHandler(index));&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; setLoaded(true);&nbsp; &nbsp; }&nbsp; }, [loaded]);&nbsp; return (&nbsp; &nbsp; <div>&nbsp; &nbsp; &nbsp; <div id="container">&nbsp; &nbsp; &nbsp; &nbsp; <div className="_2iA8p44d0WZ">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span className="chip _7ahQImy">Item One</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span className="chip _7ahQImy">Item Two</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span className="chip _7ahQImy">Item Three</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span className="chip _7ahQImy">Item Four</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span className="chip _7ahQImy">Item Five</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <input&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type="text"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; className="searchBox"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id="search_input"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; placeholder="Select"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; autoComplete="off"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; value=""&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; />&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; <div>&nbsp; &nbsp; &nbsp; &nbsp; {selectedElements.map((item, i) => (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <div key={i} className="selected-element" ref={scrollRefs.current[i]}>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <fieldset>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <legend>{item}</legend>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </fieldset>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; &nbsp; ))}&nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; </div>&nbsp; );};
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript