React'te görünüme kaydır

Nov 23 2020

İki farklı olan basit bir tepki uygulaması yapıyorum div's..

Seçilmiş giriş ve seçilen liste ile bir

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

Başka seçilen seçeneği aşağı listeler fieldset,

  <div>
    {selectedElements.map((item, i) => (
      <div key={i} className="selected-element" ref={scrollDiv}>
        <fieldset>
          <legend>{item}</legend>
        </fieldset>
      </div>
    ))}
  </div>

Bu çözüme dayanarak createRef, seçili öğeye şöyle ekledim:

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

Ardından, DOM öğelerini almak için Javascript sorgu yöntemlerini kullandım,

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

Tüm öğelere tıklama olayı dinleyicisi eklendi,

  chipsArray.forEach((elem, index) => {
    elem.addEventListener("click", scrollSmoothHandler);
  });

Sonra scrollSmoothHandlerbeğen,

const scrollDiv = createRef();

  const scrollSmoothHandler = () => {
    console.log(scrollDiv.current);
    if (scrollDiv.current) {
      scrollDiv.current.scrollIntoView({ behavior: "smooth" });
    }
  };

Ancak bu beklendiği gibi çalışmıyor.

Gereksinim:

first divİçindeki herhangi bir öğeye tıklandığında , ilgili alan kümesinin smooth scrolledbaşka bir div içine girmesi gerekir .

Ör: Kullanıcı öğesi tıklarsanız Item Fouraltında<div id="container"> ... <span className="chip _7ahQImy">Item Four</span> ... </div>

daha sonra ilgili alan kümesinin içine kaydırılması gerekir. Burada göstergeli alan kümesi Item Four..

Ben de js dom sorgu yöntemlerini react üzerinde yapmayı düşünüyorum ve bu bir tepki uygulama şekli değil gibi görünüyor. Herhangi biri, seçilen öğeye tıklandığında ilgili bir alan kümesine kaydırmanın sonucunu elde etmeme yardımcı olabilir mi?

Yanıtlar

1 DrewReese Nov 24 2020 at 13:22

Konu

  1. React.createRefgerçekten sadece sınıf tabanlı bileşenlerde geçerlidir. İşlevsel bir bileşen gövdesinde kullanılırsa, ref her oluşturma döngüsünde yeniden oluşturulur.
  2. onClickDinleyicileri DOM öğelerine eklemek için DOM sorgu seçici kullanmayın . Bunlar dışarıda canlı tepki verir ve bellek sızıntınız olmaması için bunları temizlemeyi (yani kaldırmayı) hatırlamanız gerekir. React'in onClickpervanesini kullanın .
  3. Ne zaman selectedElementseşleştirilir Eklemek aynı sonuncusu seti UI alır biridir, böylece her elemana ref.

Çözüm

  1. Kullanım React.useRefsen görünümüne kaydırmak istediğiniz her öğe eklemek için ref tepki fonksiyonel bileşen vücutta bir dizi saklamak için.
  2. Takın scrollSmoothHandlerdoğrudan her spanbireyin onClickpervane.
  3. 1.'de oluşturulan ref dizisindeki her bir referansı, kaydırmak istediğiniz her eşlenen alan kümesine ekleyin.

Kod

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.Çözüm

Eğer herhangi unsurları güncelleştiremezsiniz yana divolan id="container"ve tüm onClickişleyicileri DOM sorgulama yoluyla bağlanmaları gerekir, hala bir Körili kullanabilir scrollSmoothHandlergeri arama ve kapsamı bir dizin içine alın. İlk oluşturmadan sonrauseEffect DOM'u sorgulamak için bir kancaya ihtiyacınız olacak, böylece aralıklar monte edilmiş olacak ve bir "yüklü" durumu depolamak için bir kancaya ihtiyacınız olacak. Durumu üzerinde rerender ve yeniden içine alın tetiklemek için gerekli olan olarak geri arama.useStatescrollRefsscrollSmoothHandler

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