簡體   English   中英

在反應中滾動到視圖中

[英]Scroll into view in react

我正在制作一個簡單的反應應用程序,其中有兩個不同的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" });
    }
  };

但這並不像預期的那樣工作。

要求:

單擊first div任何項目,然后它的相關字段集需要在另一個 div 中smooth scrolled

例如:如果該元素的用戶點擊Item Four<div id="container"> ... <span className="chip _7ahQImy">Item Four</span> ... </div>

然后需要滾動到相關的字段集。 這里有傳說中的字段集Item Four ..

我認為也在反應上制作 js dom 查詢方法,這似乎不是反應的實現方式。 任何人都可以請幫助我實現在單擊所選項目時滾動到相關字段集的結果..

編輯 React 功能組件(分叉)

問題

  1. React.createRef實際上只在基於類的組件中有效。 如果在功能組件主體中使用,則 ref 將在每個渲染周期重新創建。
  2. 不要使用 DOM 查詢選擇器將onClick偵聽器附加到 DOM 元素。 這些活在外面的反應,你需要記住清理它們(即刪除它們),這樣你就不會出現內存泄漏。 使用 React 的onClick道具。
  3. selectedElements被映射時,您將相同的ref 附加到每個元素,因此最后一組是您的 UI 獲得的一組。

解決方案

  1. 在功能組件主體中使用React.useRef來存儲一組 react refs 以附加到您想要滾動到視圖中的每個元素。
  2. scrollSmoothHandler直接附加到每個spanonClick道具。
  3. 將 1. 中創建的 ref 數組中的每個 ref 附加到您要滾動到的每個映射字段集。

代碼

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

由於您無法使用id="container"更新div任何元素,並且所有onClick處理程序都需要通過查詢 DOM 來附加,因此您仍然可以使用scrollSmoothHandler回調並在范圍內包含一個索引。 您需要一個useEffect鈎子在初始渲染查詢 DOM 以便安裝跨度,以及一個useState鈎子來存儲“加載”狀態。 該狀態是觸發重新渲染並重新包圍scrollSmoothHandler回調中的scrollRefsscrollSmoothHandler

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>
  );
};

編輯滾動到視圖中的反應

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM