DEV Community

Create section navigation with React and Intersection Observer

Maciek Grzybek on July 05, 2019

Create section navigation with React and Intersection Observer Introduction For one of the last project at work, I had to c...
Collapse
 
thatfemicode profile image
thatFemicode

Hi Maceik, came across this article and i must say it is really helpful but i am trying to create something like this website olaolu.dev/ where those boxes by the sides are the navigators but i keep getting error, do you by any means have a solution to something like that, i'd be really grateful, tried using static data and i am still getting the errors

Collapse
 
maciekgrzybek profile image
Maciek Grzybek

Hey, I'd need more details, a repo or a code sandbox, it's really hard to help without more information :)

Collapse
 
thatfemicode profile image
thatFemicode

github.com/thatFemicode/Landing
Here is a link to the repo, i am trying to recreate what you did with the intersection observer api but for navigation like the link i sent to you where each section that comes in makes the circles background turn black

Thread Thread
 
thatfemicode profile image
thatFemicode • Edited

I am not sure i am explaining well, instead of looping over several characters, the sections will have their own ref, i keep getting errors, been on it since yesterday night, if you notice from the link i sent earlier olaolu.dev/, there are boxes that keeps track of the section. do you get me now?, i'd be really grateful if you can assist me in making this work, thanks a lot

Thread Thread
 
thatfemicode profile image
thatFemicode

I think i have a better explanation now, yes
so with refernce to that website i sent olaolu.dev/ what i want to achieve with your approach using the IO API is to have a navigator (the boxes or circles) that can be clicked on and goes directly to a section either be it home or gallery and once a particular section is in view, the circle or box now has a style it gives like as shown in the website i sent. Just like yours using static data where you click on the names which serves as navigator and the particular character comes into the viewport then both the navigator and character get the yellow background, I keep getting errors since i am not looping over. i have done somethings on the github repo i sent. I'd be really greatful if you can assist me.

Collapse
 
thatfemicode profile image
thatFemicode

I'd make a repo and share now

Thread Thread
 
maciekgrzybek profile image
Maciek Grzybek

I'll take a look later today and will let you know :)

Thread Thread
 
thatfemicode profile image
thatFemicode

Wow, thanks a lot you are so kind 🙏
this is a link to a codesandbox
codesandbox.io/s/tender-oskar-rvbz...

Thread Thread
 
maciekgrzybek profile image
Maciek Grzybek

So it looks like you're not really storing anything in your refs object. As you can see in my example, ref needs to be attached to html element, like this:

 <div  ref={characterRef} />
Enter fullscreen mode Exit fullscreen mode

If you want to get the ref from inside of some other component, you'll have to use forwardRef -> reactjs.org/docs/forwarding-refs.html

That's why you're getting errors

Thread Thread
 
thatfemicode profile image
thatFemicode • Edited

Please is this an issue you could assist me in solving, just started using react of recent and i need this for the project.

Thread Thread
 
thatfemicode profile image
thatFemicode

I'd be really grateful if you could assist me with this

Thread Thread
 
thatfemicode profile image
thatFemicode

@maciekgrzybek can you please assist with this, i have literally tried everything i know nothing just works, been on it sice you told me about the forwardref and still not gotten anywhere

Thread Thread
 
maciekgrzybek profile image
Maciek Grzybek • Edited

Sorry mate, I wish I could help but I'm really busy with my other projects. Everything you need to know should be in this article, basically ref needs to be attached to an actual dom element and currently you just passing them to the components. Some more reading ->

Thread Thread
 
thatfemicode profile image
thatFemicode

Thanks, I'd look for an alternative if i cant find a solution, really appreciate 🙏

Thread Thread
 
thatfemicode profile image
thatFemicode

Hi there @maciekgrzybek sorry for disturbing you agai, i found a way to make the scrolling to each section work but then i cant make the io and the active class work, could you please assit me with that in your free time. Here is a codepen link
codesandbox.io/s/eager-agnesi-virvq

Thread Thread
 
maciekgrzybek profile image
Maciek Grzybek

Hey man, sorry wasn't here for a while, did you manage do sort this out?

Thread Thread
 
thatfemicode profile image
thatFemicode

Sort of, found another way but your method looked really nice also wish I could have broken it down better
Here is a link to what I did with it
nba-landing.netlify.app/

Thread Thread
 
maciekgrzybek profile image
Maciek Grzybek

You were really close, you just didn't pass the correct name to activeCharacter state :)

Thread Thread
 
thatfemicode profile image
thatFemicode

Sorry could you do that and let me see where I made the mistake,probably fork the sandbox and send an updated link. Happy holidays

Thread Thread
 
maciekgrzybek profile image
Maciek Grzybek

In this useEffect:

  useEffect(() => {
    const observerConfig = {
      rootMargin: `-${
        pageHeight % 2 === 0 ? observerMargin - 1 : observerMargin
      }px 0px -${observerMargin}px 0px`,
    };
    const handleIntersection = function (entries) {
      entries.forEach((entry) => {
        if (entry.target.id !== activeCharacter && entry.isIntersecting) {
          setActiveCharacter(entry.target.id);
        }
      });
    };
    const observer = new IntersectionObserver(
      handleIntersection,
      observerConfig
    );
    // observer.observe(refs.name);
    return () => observer.disconnect(); // Clenaup the observer if component unmount.
  }, [
    activeCharacter,
    setActiveCharacter,
    observerMargin,
    refs,
    items,
    pageHeight,
    name,
  ]);
Enter fullscreen mode Exit fullscreen mode

You need to observe for each element, now you're not really observing anything. Notice how in my tutorial, each character is a separate component, and each one of them has its own Observer attached to it.

Thread Thread
 
thatfemicode profile image
thatFemicode

I keep getting the husband error
Argument 1 ('target') to IntersectionObserver.observe must be an instance of Element

Thread Thread
 
thatfemicode profile image
thatFemicode

Now I am observing for with refs.name but still getting that error

Thread Thread
 
thatfemicode profile image
thatFemicode

Now I am observing with refs.name but still getting that error

Thread Thread
 
maciekgrzybek profile image
Maciek Grzybek

There is no such a thing like refs.name in you code. Console log it and see what you are getting. If you want to access ref with specific name you need to access it with refs[name]. Also, you need to add a observer for each name.

Thread Thread
 
thatfemicode profile image
thatFemicode

Thanks Maceik, i'll look at your approach again once i am free cus right now tbh i am not really getting what i am doing again cus i had to learn a lot two weeks ago

Collapse
 
alanominator profile image
Alanominator • Edited

I found bag. When you click navigation button and stop scroll by touching screen, button, that has been clicked, has active class until another button is clicked.

I created own section-navigation. The same idea, but other decisions.

Collapse
 
sirluis profile image
Luis Henrique

Unnecessarily complicated, mixing graphql and a lot of non related stuff on an article about Intersection Observer + React. I'm sorry for the newbie people on web development who are reading this and have no idea on what is graphql and gql etc.

Collapse
 
maciekgrzybek profile image
Maciek Grzybek

Well, that's your opinion :)

Collapse
 
maciekgrzybek profile image
Maciek Grzybek

I can explain it to you if you need.

Collapse
 
takhine profile image
Aniketh Nair

I believe this gives beginners the opportunity to upgrade themselves so thanks for that!

Collapse
 
sebastiangraz profile image
Sebastian Grąz

Hi Maciek, thanks for the write-up! It helped me a lot in getting started with IO + hooks. In my own implementation I found a way to make the rootMargin configuration simpler than using a 1px pixel window height listener. While achieving the same thing.

{
  rootMargin: "-50% 0px -50% 0px",
  threshold: 0,
}
Enter fullscreen mode Exit fullscreen mode

Hope this helps someone else stumbling upon this post.

Collapse
 
maciekgrzybek profile image
Maciek Grzybek

Oh wow, that's way better than my approach :) Awesome stuff, thanks :) BTW - great designs mate :)

Collapse
 
sandeshsapkota profile image
sandeshsapkota • Edited

HI Maciek ! I get so confuesd to implement on my project because of gql things. do you have same kind of more simplified examples ?

Collapse
 
maciekgrzybek profile image
Maciek Grzybek

Hey yeah I can create something. I'll post a link later today OK?

Collapse
 
sandeshsapkota profile image
sandeshsapkota

Okay. thanks.

Thread Thread
 
maciekgrzybek profile image
Maciek Grzybek

Hey, sorry for the delay, I had a busy weekend :) Here's an example without the GraphQL -> github.com/maciekgrzybek/react-sec...

It's using static data in data.json file. Hope that helps :) Let me know if you need anything else.

Thread Thread
 
sandeshsapkota profile image
sandeshsapkota

A big thank you! I really appreciate this.

Collapse
 
maciekgrzybek profile image
Maciek Grzybek

Hi Akmal, thanks for the comment. Good spot, I totally forgot about it :) I've already updated example code and the demo. Not sure what do you mean about that Codesandbox example though. Looks like the code it's spot on. Could you explain? Thanks :)

Collapse
 
eliasguenther profile image
Elias Günther

Thanks! Helped a lot!!

Collapse
 
maciekgrzybek profile image
Maciek Grzybek

Glad it did :)

Collapse
 
emmaccen profile image
Lucius Emmanuel Emmaccen

Apt!