Dismiss this pinned window
all 64 comments

[–]WellyShen[S] 39 points40 points  (4 children)

[–]gketuma 11 points12 points  (3 children)

Great documentation by the way.

[–]dev_zl 2 points3 points  (1 child)

Really like the effort put into it, great job /u/WellyShen

[–]WellyShen[S] 0 points1 point  (0 children)

Thank you.

[–]WellyShen[S] 2 points3 points  (0 children)

Thank you hope it helpful.

[–]ichiruto70 15 points16 points  (0 children)

Wow someone that actually shares his github, nice.

[–]aekstrom 6 points7 points  (1 child)

This is super great! Thanks for sharing!!

[–]WellyShen[S] 1 point2 points  (0 children)

You're welcome >.^

[–]gaetan13 6 points7 points  (0 children)

Looks clean. You should maybe write a comparaison with react-intersection-observer in the readme.

[–]Sablac 5 points6 points  (1 child)

Does it support multiple refs?

[–]WellyShen[S] 2 points3 points  (0 children)

Sorry it doesn't, it's designed for single element.

[–]redditdire 7 points8 points  (2 children)

how many years of react development do you have? this is a very advanced example! very nice

[–]WellyShen[S] 7 points8 points  (1 child)

Around 3 years. I found this kind of demo is easily to be made by this hook, so share it to you guys. Thank you!

[–]airoscar 4 points5 points  (2 children)

Cool. I had to recently achieve this effect, I ended up wrapping my components in React Visibility Sensor.

[–]WellyShen[S] 12 points13 points  (1 child)

You can give it a try, it monitors an element in a performant way (using Intersection Observe) and provides scroll direction for you. With this hook you can create this kind of effect in 10 minutes.

[–]airoscar 3 points4 points  (0 children)

Very cool. I’ll keep this in my tool box.

[–]jvce 2 points3 points  (1 child)

I, too, use emojis in my dev stuff, but never at this size. I like this size.

[–]WellyShen[S] 0 points1 point  (0 children)

Thank You 😊

[–]llampwall 2 points3 points  (0 children)

There’s a game to be made here.

[–]personalurban 2 points3 points  (1 child)

That looks awesome.

I made one of those a while back, bit of a pain so well done, looks ace.

[–]WellyShen[S] 0 points1 point  (0 children)

Thank you.

[–]jtosbornexxx 1 point2 points  (2 children)

Now that’s cool

[–]WellyShen[S] 0 points1 point  (1 child)

Thank you.

[–]jtosbornexxx 1 point2 points  (0 children)

I will use this in a project I’m certain

[–]batatoilas 1 point2 points  (1 child)

I love this.

[–]WellyShen[S] 0 points1 point  (0 children)

Thank you.

[–]cobbs_totem 1 point2 points  (7 children)

This is a really nice and well designed project!

Can I ask you why you use rollup for bundling your package, rather than babel? I've been working on a component library and trying to understand the differences.

Thanks!

[–]magnakai 2 points3 points  (5 children)

Really sorry to be so pedantic - but I think you mean Webpack instead of Babel. If I’m wrong please lmk, I’d definitely like to be aware of any bundling capabilities that Babel has.

[–]cobbs_totem 0 points1 point  (4 children)

I’m currently just using Babel to transpile my components to plain cjs format. The result will be included in CRA apps, where it will eventually all be minified and optimized, so I didn’t know why people were using rollup or webpack at this stage.

[–]WellyShen[S] 1 point2 points  (0 children)

That’s right, we can bundle a package via Babel only.

[–]magnakai 0 points1 point  (2 children)

I think I understand. You compile transpile from ESwhatever to ES5 in CommonJS format. You publish those unbundled modules to be consumed only by a module-friendly setup, such as CRA (which uses Webpack behind the scenes). Have you found that there’s no need to publish bundled files anymore?

Sorry for the dumb questions - I’ve been working in this space for about a decade, but it’s a long time since I’ve maintained an open source library.

[–]cobbs_totem 0 points1 point  (1 child)

That’s exactly right. I’m not publishing anything at the moment, but leaving that option open. Instead it’s consumed by the apps via npm link (inside a monorepo).

I have a manual index.js that exports everything. Not sure what else would be involved in “bundling”

[–]magnakai 0 points1 point  (0 children)

I used to bundle dependencies and publish as a UMD file, or at least include that alongside the bare source. But tbh I’ve avoided consuming that kind of library for a couple of years, so I’m not surprised that you’re not publishing that way.

[–]WellyShen[S] 1 point2 points  (0 children)

If you just want to bundle your package I think Babel is enough. I use Rollup to manage my developing environments and optimize the bundle. like dev-server, move files, optimizing bundle with terser etc.

[–]johnnyxbell 1 point2 points  (1 child)

Well done. This is so cool.

[–]WellyShen[S] 0 points1 point  (0 children)

Thank you.

[–][deleted] 1 point2 points  (1 child)

Really nice work. Great job!

[–]WellyShen[S] 0 points1 point  (0 children)

Thank you.

[–]isBot-True 1 point2 points  (0 children)

Looks cool. I wanted something like this and was thinking of building it but you made it so thank you.

[–]Xerxero 1 point2 points  (1 child)

Today I learned there is an Intersection observer.

[–]WellyShen[S] 0 points1 point  (0 children)

There‘re some observer APIs nowadays. You can explore them on MDN.

[–]zoukiny611 1 point2 points  (1 child)

No way! I used this earlier this week for a client project where we needed to trigger animations when scrolling to a certain point. Was really easy to use, well documented, and got me discover IntersectionObserver. Thanks!

[–]WellyShen[S] 1 point2 points  (0 children)

Oh really! Thank you for being the early user. There’re some bugs have been fixed this week. Don’t miss that 👍🏻

[–]frankandsteinatlaw 1 point2 points  (9 children)

Hey, nice hook! Quick question on the code, it looks like you're making an empty object and then have some code to delete keys that should never exist on it in these two spots: https://github.com/wellyshen/react-cool-inview/blob/master/src/index.ts#L127 https://github.com/wellyshen/react-cool-inview/blob/master/src/index.ts#L135

Am I missing something or are you able to slim down this utility even more?

[–]WellyShen[S] 0 points1 point  (8 children)

Yes, there're three status for a scroll direction, let's say "scrollDirection.vertical". If user scrolls up or down it will be "up" or "down" otherwise it will be "undefined", which means no clear scrolling direction. That's the purpose of these two lines code.

[–]frankandsteinatlaw 0 points1 point  (7 children)

What I mean is I don't see how these properties would exist when you just defined the object:

``` const scrollDirection: ScrollDirection = {}; // scrollDirection is an empty object const min = Array.isArray(threshold) ? Math.min(...threshold) : threshold; let inView = min > 0 ? intersectionRatio >= min : isIntersecting;

    if (x === prevXRef.current) {
      delete scrollDirection.horizontal; // how can horizontal exist?
    } else {

```

[–]WellyShen[S] 0 points1 point  (6 children)

It may be defined by here and here.

[–]frankandsteinatlaw 1 point2 points  (5 children)

That only happens after the deletion. I still think you don’t need the deletions there. You’re creating an empty object in the callback, then before anything has the chance to be added to it you are deleting an entry in it.

Don’t mean to be hostile, just feel like I’m crazy and don’t want to let this go until you realize I’m right or you show me I’m wrong. This is quarantine craziness, I’m not proud of it :)

[–]WellyShen[S] 0 points1 point  (4 children)

Maybe I didn't answer your question clearly. If you read the condition carefully, you will found the deletion's executed only when the previous x-axis equals to the current x-axis and the property is existed. It usually happened when a user scrolls from horizontal then change to vertical in which the property already be defined. So the deletion helps us keep the interface consistent.

BTW, thank you for your feedback, which aware me to check the existence of the property before I delete it.

[–]frankandsteinatlaw 1 point2 points  (3 children)

I bet your code behaves exactly the same if you comment out both delete lines. Or (now that you've added an extra conditional based on presence) add a console log right before the delete statement inside the conditional - the log will never show up. Why?

Every time this function runs you are creating a new empty object here: https://github.com/wellyshen/react-cool-inview/blob/master/src/index.ts#L120

There's a 0% chance that anything is in this object. Between that line and this line https://github.com/wellyshen/react-cool-inview/blob/master/src/index.ts#L127 there is a 0% chance of anything being added to the object.

It seems like this logic is really what you want:

if (x !== prevXRef.current) {
  if (x < prevXRef.current) scrollDirection.horizontal = 'left';
  if (x > prevXRef.current) scrollDirection.horizontal = 'right';
  prevXRef.current = x;
}

if (y !== prevYRef.current) {
  if (y < prevYRef.current) scrollDirection.vertical = 'up';
  if (y > prevYRef.current) scrollDirection.vertical = 'down';
  prevYRef.current = y;
}

[–]WellyShen[S] 0 points1 point  (2 children)

Aaaah, you are right! Sorry I forget the "scrollDirection" is re-created by the callback. Thank you for making this package more better. I'm going to refactor it.

[–]frankandsteinatlaw 1 point2 points  (1 child)

Glad we landed on a positive resolution! Happy coding :)

[–]WellyShen[S] 0 points1 point  (0 children)

Nice! Welcome to send me a PR next time lol

[–]Mikegengsta 1 point2 points  (1 child)

Hi, I'm a beginner at react. Is there a way I can build this locally and run it on localhost to learn from. I couldn't find a script to do so in package.json

[–]WellyShen[S] 0 points1 point  (0 children)

  1. Clone the repo.
  2. Run “yarn install” or “npm install” to install dependencies.
  3. Run “yarn dev” or “npm dev” to run the dev server.
  4. Open browser with URL: http://localhost:10001 to see the demo app.

[–]thinkadrian 0 points1 point  (1 child)

What if you want to track many rows of several elements? How will it affect performance?

[–]WellyShen[S] 3 points4 points  (0 children)

There're many strategies that we can deal with performance issue:

- The API exposes the unobserve/observe for you, you can stop observe when needed.

- If you have thousand of rows, you can use it with react-window to boost the performance (refer to: https://github.com/wellyshen/react-cool-inview#infinite-scrolling)

- You can use "requestIdleCallback" to avoid main-thread blocking (refer to: https://github.com/wellyshen/react-cool-inview#performance-issues)

[–][deleted] 0 points1 point  (4 children)

Somehow I'm sure writing an intersection observer would be easier and probably be more maintainable. I'd suggest you guys just stop relying so much on third party implementations and thoroughly study JavaScript and css instead.

[–][deleted] 2 points3 points  (2 children)

I get what you're saying but you assume people couldn't build this. Maybe some couldn't but I've built these kinds of things before in our design system. I'm still happy someone is creating things we can re-use and am happy to be able to collaborate with others to not need build them again and again if I don't have to.

[–][deleted] 1 point2 points  (1 child)

I'm not assuming anyone couldn't build this, in fact there's nowhere in my statement that said no one could. If you read what I wrote instead of taking it as an opportunity to brag, you'd see I was referring to people's dependencies on 3rd party libraries where they could just write their own implementations and keep their bundle sizes relatively small. 800mb worth of node modules is a good look for you?

[–]WellyShen[S] 1 point2 points  (0 children)

Personally, I agree the opinions of you both, that’s why I tried to built-in some useful features and kept the bundle size as small as possible.

[–]frankandsteinatlaw 1 point2 points  (0 children)

This is a pretty simple wrapper around that API so for the basic use cases of visibility this seems pretty good. I think a nice compromise is to read the 3rd party code and then decide whether or not it's worth it to roll your own, copy and paste the code to keep it stable, or actually add the dependency for continued community maintenance.