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

Usage with React #6

Open
mod3x opened this issue Aug 14, 2020 · 11 comments
Open

Usage with React #6

mod3x opened this issue Aug 14, 2020 · 11 comments
Labels
question Further information is requested

Comments

@mod3x
Copy link

mod3x commented Aug 14, 2020

Hey there. Is it safe to use with react lifecycle hooks? As I noticed nanopop has no method to destroy an instance and react will try to create another one every re-render. Thanks

@mod3x
Copy link
Author

mod3x commented Aug 14, 2020

here is example snippet

React.useLayoutEffect(() => {
  if (!isOpened) {
    return
  }

  const _reference = reference.current
  const _popper = popper.current

  let nanopop: NanoPop

  if (_reference && _popper) {
    nanopop = new NanoPop(_reference, _popper, {
      margin: 4,
      position: 'bottom-end',
    })

    nanopop.update()
  }
  
  // expected behavior
  return () => nanopop.destroy()
}, [isOpened])

@simonwep
Copy link
Owner

Hi :) NanoPop does not need to be destroyed manually as it does not bind any events to an elemenet. The only reason for re-creating a class is that it's convenient to just call .update() without re-providing any options. If a nanopop instance falls out of scope it'll get garbage collected automatically, no need to do any cleanup manually.

@simonwep simonwep added the question Further information is requested label Aug 14, 2020
@simonwep
Copy link
Owner

simonwep commented Aug 14, 2020

Maybe it was a bad design decision to use a class, I'll consider releasing a second version with just a function called usePopper or something like that to make it look less stateful (considering that using new is quite expensive).

@7iomka
Copy link

7iomka commented Aug 14, 2020

Maybe it was a bad design decision to use a class, I'll consider releasing a second version with just a function called usePopper or something like that to make it look less stateful (considering that using new is quite expensive).

I would be very grateful to you!

@mod3x
Copy link
Author

mod3x commented Aug 14, 2020

it does not bind any events to an elemenet

That lib becomes even better for me lol. Thanks, I think you can close this issue. Cheers

@7iomka
Copy link

7iomka commented Aug 14, 2020

it does not bind any events to an elemenet

That lib becomes even better for me lol. Thanks, I think you can close this issue. Cheers

Can you show me your example of using this plugin? I want to create my own dropdown and use this plugin as a dropdown content positioning tool.
I have a problem that the reference element is missing in the dom, so I cannot initialize the plugin. The workaround that I use is to wait for the time when the content is first mounted in the dom (I use portals), at which point I initialize nanoPop for the first time)
Thanks

@simonwep
Copy link
Owner

Version 2 is in progress... I hope this will only take a few days and I'll ping you @7iomka as soon as it's "finish" since there are major API changes :)

@mod3x I'll keep this open as long as the second version is in progress, you made me realize that the current API doesn't make that much sense as it's a really low level library to position things. At first I tried to imitate Popper but this is definitely going in a completely separate direction! 😄

@simonwep
Copy link
Owner

Okay I've managed to create a minimal demo on codesandbox. Make sure to checkout the latest README :)

@mod3x
Copy link
Author

mod3x commented Aug 19, 2020

Great work! I'll update to the v2 :)

@7iomka
Copy link

7iomka commented Aug 20, 2020

Okay I've managed to create a minimal demo on codesandbox. Make sure to checkout the latest README :)

Thank you!
One question: I see your content of dropdown is always prerendered and persist on page. In real-world projects we have dynamically created content (like from api) or static content, but displayed with React.createPortal only if dropdown is opened (local state changed by click on trigger). It is possible to handle this case? Same question is for case when component that has ref of trigger - changed.

In prev. version of your lib i write this code

...
    const [pop, setPop] = React.useState(null);
    const prevTrigger = usePrevious(trigger);
    const refUpdate = React.useRef(false);
    useEffect(() => {
      const isEqKeys = trigger?.key === prevTrigger?.key;
      if (!isEqKeys) {
        refUpdate.current = true;
      }
      if (pop && !refUpdate.current) return;
      if (!refTrigger?.current || !refContent?.current) return;
      if (!isOpen) return;
      setPop(
        new NanoPop(refTrigger.current, refContent.current, {
          forceApplyOnFailure: true,
          position: position || 'bottom-middle',
          variantFlipOrder: {
            start: 'sme',
            middle: 'mse',
            end: 'ems',
          },
          positionFlipOrder: {
            top: 'tb',
            right: 'rltb',
            bottom: 'bt',
            left: 'lrbt',
          },
        }),
      );
      refUpdate.current = false;
    }, [pop, isOpen, trigger, prevTrigger, refContent?.current, refTrigger?.current]);

    useEffect(() => {
      // eslint-disable-next-line no-unused-expressions, @typescript-eslint/no-unused-expressions
      showPortal && pop && pop.update();
    }, [pop, showPortal, windowWidth, windowHeight]);
...

@7iomka
Copy link

7iomka commented Aug 20, 2020

My current hack-workaround (with css animation + delay)
https://codesandbox.io/s/distracted-haibt-15li4?file=/src/App.js
Interesting your comments on this

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

No branches or pull requests

3 participants