Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability access the ref instance so I can use react-intersection-observer with existing refs #186

Open
kauffmanes opened this issue Feb 17, 2021 · 1 comment

Comments

@kauffmanes
Copy link

Hey there, I'm not sure if this is a feature request or just me misunderstanding how this library should work.

I'm working on a catalog page where I have a dropdown navigation with categories, and when you select one (ex. vegetables), it scrolls to that category section of vegetables. That part works fine without this library, but I wanted to add the ability to update the dropdown with the section currently is in view, so I'm trying to do that with the react-intersection-observer hook.

I made a Codepen of what my code looks like now:
https://codepen.io/kauffmanes/pen/poNPYyW

And this is what I was trying to do using react-intersection-observer:

// doesn't do anything yet
const handleChange = (entry) => {
  console.log(entry.isIntersecting);
}

const categoryRefs = categories.reduce((acc, value) => {
    const [ref] = useIntersectionObserver(handleChange, {
        threshold: 0,
        rootMargin: '0% 0% -75%'
    });
    acc[value.id] = ref;
    return acc;
}, {});

/* currentCategory is a prop reflecting the ID of the currently selected category, ex. 'vegetables'. 
So when currentCategory changes, the effect is called. This code obviously doesn't work anymore 
because the ref returned by useIntersectionObserver doesn't include the instance. Is there another way
 I can access the instance so I can scroll to it? Or, should I be maintaining two refs? */
useEffect(() => {
    const scrollableRef = categoryRefs[currentCategory];
    if (scrollableRef) {
        const offsetTop =
            scrollableRef.current.offsetTop >= 100
                ? scrollableRef.current.offsetTop - 100
                : scrollableRef.current.offsetTop;
        window.scrollTo(0, offsetTop);
    }
}, [currentCategory]);

// in the render method:
<>
    {categories.map((category) => (
        <div ref={categoryRefs[category.id]}>{category.title}</div>
        // other stuff
    )}
</>

Expected behavior

I want to be able to use the refs created by react-interaction-observer so I get your library functionality in addition to the scrolling functionality I already had.

Current behavior

useIntersectionObserver doesn't return an instance that I can use so I'm unable to use this library without breaking existing functionality. If this is possible, I can try to submit a storybook recipe once it's working.

Context (environment)

  • Version: React 16.8.6
  • Platform: Darwin Emilys-MacBook-Pro.local 19.6.0 Darwin Kernel Version 19.6.0: Tue Nov 10 00:10:30 PST 2020; root:xnu-6153.141.10~1/RELEASE_X86_64 x86_64
@Rendez
Copy link
Contributor

Rendez commented Feb 19, 2021

The API should be changed by allowing you to pass the innerRef used optionally, but we never got to do this. This is for historical reasons, where creating refs wasn't a thing in React yet, but merely string or callback was your only option.

I believe the hook api should definitely allow you to pass innerRef which would then be used as the instanceRef internally.

For now, you'll have to do it like so:

const observerRefs = categories.reduce((acc, value) => {
    const [ref] = useIntersectionObserver(handleChange, {
        threshold: 0,
        rootMargin: '0% 0% -75%'
    });
    acc[value.id] = ref;
    return acc;
}, {});

const categoryRefs = categories.reduce((acc, {id}) => {
    acc[value.id] = createRef();
    return acc;
}, {});
<>
    {categories.map((category) => (
        <div ref={(node) => {
          observerRefs[category.id](node) // assign this div internally for the intersection observer to give you change events
          categoryRefs[category.id].current = node;
        }}>{category.title}</div>
    )}
</>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants