• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

React - Komponent bez renderu

0 głosów
253 wizyt
pytanie zadane 20 sierpnia 2021 w JavaScript przez nielotweb Bywalec (2,240 p.)

Cześć, aktualnie uczę się Reacta i mam pewien problem ze zrozumieniem pewnej rzeczy. A dokładnie: Postanowiłem zrobić sobie skrypt który będzie chwytał wszystkie linki na stronie z klasą "hover-this" i potem po najechaniu na jeden z nich zaczął się lekko przesuwać ( przez transform: translate ) - ale to nie problem w samym skrypcie. Problem jest jak to "zamontować" w reactie. W czystym JS zrobiłem sobie <script></script> wrzuciłem cały kod w te tagi i śmigało - a jak to zrobić w reactie?

Na początku zrobiłem normalny komponent funkcyjny w którym dodałem cały kod, a w środku rendera (return) nic nie dałem puste miejsce (<> </>) - i wrzuciłem do głównego pliku App.js gdzie ładowane są wszystkie komponenty ale tam nawet nie łapie linków. Nie mogę sobie tego w głowie ułożyć na jakiej zasadzie mają działać takie odrębne skrypty które nic nie zwracają a coś robią w tle. Ktoś coś? Z góry dziękuję!

A tutaj kod tego skryptu w tym komponencie: 

const LinksHover = (props) => {

    const links = document.querySelectorAll(".hover-this");

    const animateIt = function (e) {
        const a = this.querySelector("span");
        const { offsetX: x, offsetY: y } = e,
        { offsetWidth: width, offsetHeight: height } = this,

        move = 25,
        xMove = x / width * (move * 2) - move,
        yMove = y / height * (move * 2) - move;

        a.style.transform = `translate(${xMove}px, ${yMove}px)`;

        if (e.type === "mouseleave") a.style.transform = '';
    }

    links.forEach(b => b.addEventListener('mousemove', animateIt));
    links.forEach(b => b.addEventListener('mouseleave', animateIt));

    return(
        <>
        </>
    )
}

export default LinksHover;

 

komentarz 20 sierpnia 2021 przez ScriptyChris Mędrzec (190,190 p.)

Gdzie tworzone są te linki i jak używasz komponentu LinksHover?

komentarz 20 sierpnia 2021 przez nielotweb Bywalec (2,240 p.)

Linki są w różnych komponentach na całej stronie (np. menu) - A komponent LinksHover używałem importując do głównego pliku App.js w metode return() - ale w ten sposób nie wyłapywało linków. 

Ale już ktoś poniżej dał dobrą odpowiedź, żeby to wrzucić w useEffect w App.js zamiast odrębny komponent robić do tego - i to działa - tylko pytanie czy to dobry sposób czy można to lepiej zrobić, lub powinno inaczej się takie rzeczy robić?

1
komentarz 20 sierpnia 2021 przez ScriptyChris Mędrzec (190,190 p.)

Twoje podejście jest dość nisko poziomowe i praktycznie pomija kontekst Reacta, bo pobierasz linki bezpośrednio z DOM, a eventy na linkach obsługujesz również przez DOM-ową metodę.

Wg mnie lepiej tutaj skorzystać z kompozycji, otaczając każdą listę z linkami komponentem, który będzie obsługiwał eventy na tych linkach, albo przekazywać do tego komponentu dane, na podstawie których on wyświetli listę linków z obsługą eventów.

Przykłady:

const list = [
  {
    id: 1,
    text: 'qwe'
  },
  {
    id: 2,
    text: 'asd'
  },
  {
    id: 3,
    text: 'zxc'
  },
];

const list2 = [
  {
    id: 7,
    text: 'iop'
  },
  {
    id: 8,
    text: 'jkl'
  },
  {
    id: 9,
    text: 'bnm'
  },
];

function App {
  return <>
    <ListWrapper listData={list}/>

    <ListDecorator>
      {() => {
        return list2.map(listItem => (
          <ul key={listItem.id}>
            <li>{listItem.text}</li>
          </ul>
        ))
      }}
    </ListDecorator>
  </>
}

function ListWrapper({ listData }) {
  const onMouseOver = (event) => console.log('mouseover wrapper event:', event);

  return listData.map(listItem => (
    <ul key={listItem.id}>
      <li onMouseOver={onMouseOver}>{listItem.text}</li>
    </ul>
  ))
    
}

function ListDecorator({ children }) {
  const onMouseOver = (event) => console.log('mouseover decorator event:', event);

  return <div onMouseOver={onMouseOver}>
    {children()}
  </div>
}

Pierwsze podejście to zwyczajne przekazanie danych przez propsy i oddelegowanie do komponentu renderowania, łącznie z podpięciem event handlera na każdy element listy. Drugie podejście korzysta z funkcji children i jedynie podpina event handler na dekorator gotowej listy dostarczonej z góry, korzystając z mechanizmu event delegation - trzeba wtedy samemu zaimplementować filtrowanie odpowiednich elementów, żeby nie brać pod uwagę tych, które nie są elementami listy.

W drugim przypadku można by też skorzystać z ref'a przekazanego jako parametr do funkcji children (i wtedy podpiąć go wewnątrz bezpośrednio na listę), aby nie tworzyć dodatkowego <div>a wokół listy zwróconej przez tą funkcję.

1 odpowiedź

+2 głosów
odpowiedź 20 sierpnia 2021 przez wizarddos Nałogowiec (27,970 p.)
Spróbuj wrzucić ten kod do useEffect() w komponencie App.
1
komentarz 20 sierpnia 2021 przez nielotweb Bywalec (2,240 p.)
A faktycznie, to było takie proste - totalnie zapomniałem, że useEffect jest od takich rzeczy..

Działa więc dzięki wielkie!

Podobne pytania

+1 głos
2 odpowiedzi 684 wizyt
pytanie zadane 29 maja 2021 w JavaScript przez ShockWave Bywalec (2,350 p.)
0 głosów
2 odpowiedzi 2,789 wizyt
pytanie zadane 2 maja 2020 w JavaScript przez kalczur Gaduła (4,320 p.)
0 głosów
1 odpowiedź 642 wizyt
pytanie zadane 25 marca 2021 w Inne języki przez karolina_web Nowicjusz (140 p.)

93,600 zapytań

142,524 odpowiedzi

322,993 komentarzy

63,085 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...