Temzasse / react-modal-sheet

Flexible bottom sheet component built with Framer Motion to provide buttery smooth UX while keeping accessibility in mind 🪐
https://temzasse.github.io/react-modal-sheet/
MIT License
830 stars 79 forks source link

Unable to pass ref to Sheet.Content or children within #32

Closed ghost closed 3 years ago

ghost commented 3 years ago

Hi, I want to use the useElementScroll from framer motion to animate the children inside Sheet.Content. But it seems that the ref remains undefined.

Below is the code example:

https://codesandbox.io/s/serverless-fast-l6w90

Temzasse commented 3 years ago

Hi @lodisy 👋🏻

The reason why the ref isn't working as you expect is because the internals of the sheet are not rendered until the sheet is opened. You can get around this issue by moving the internals into a separate component and setup all the scroll handlers there:

import React from "react";
import "./styles.css";
import { useElementScroll } from "framer-motion";
import Sheet from "react-modal-sheet";

export default function App() {
  let [isOpen, setOpen] = React.useState(false);
  let toggle = () => setOpen(!isOpen);

  return (
    <div className="App">
      <button onClick={toggle}>toggle</button>
      <Sheet isOpen={isOpen} onClose={() => setOpen(false)}>
        <SheetInner />
      </Sheet>
    </div>
  );
}

function SheetInner() {
  let contentRef = React.useRef(null);
  let { scrollY } = useElementScroll(contentRef);

  React.useEffect(() => {
    scrollY.onChange(() => {
      console.log("scrolling");
    });
  }, [scrollY]);

  return (
    <Sheet.Container>
      <Sheet.Content ref={contentRef} style={{ overflowY: "scroll" }}>
        {Array.from({ length: 50 })
          .fill(1)
          .map((_, i) => (
            <div
              key={i}
              style={{
                height: 200,
                width: "100%",
                margin: 16,
                backgroundColor: "#eee"
              }}
            >
              {i}
            </div>
          ))}
      </Sheet.Content>
    </Sheet.Container>
  );
}

I tested this in your sandbox and it should work.

I hope this helps 🙂