zeckdude
zeckdude

Reputation: 16173

Why does using React Context with Framer Motion not work?

I have a version of a slideshow where the state is being stored locally, you can see that the slideshow works great and the slide components only are unmounted once the animation is complete. https://stackblitz.com/edit/react-framer-motion-slideshow-official?file=src%2FSlideShow.js

Once I added the context to handle the values, the animation sliding still works but the exiting component is replaced with the new slide content when the animation begins, which looks really strange. Also the custom value for the slide directions seems to be broken. https://stackblitz.com/edit/react-framer-motion-slideshow-official-context?file=src%2FSlideShow.js

Do you have any ideas how I can get the animation to work correctly again when using context?

Upvotes: 2

Views: 1205

Answers (1)

Joshua Wootonn
Joshua Wootonn

Reputation: 1276

Everything that consumes a context re-renders every time that context’s state changes. So the children of your Slides component

  1. rerender
  2. see that the new variant = to the next state
  3. appear at the destination

If I were you I wouldn't use context. If you really want to not explicitly pass the same props over and over you can do

          {[
            MainSettingsSlide,
            ChangeLanguageSlide,
            LanguageDetailsSlide,
            BlockedSitesSlide
          ].map((Component, i) => (
            <Component
              activeSlideName={activeSlideName}
              onNavigateSidebar={onNavigateSidebar}
              key={i}
            />
          ))}

Sorry for the indirect answer :)

Edit two days later

In rereading your question I realize there are some other problems

  1. You need to always conditionally render based on props not context
const Slide = ({ children, slideName, className, activeSlideName }) => {
  // This context will update outside of framer-motion
  // framer-motion animating something in while it is animating something out is
  // predicated on you giving it control by using props
  // const { activeSlideName } = useSlideShowContext();

  // console.log('activeSlideName in Slide', activeSlideName);
  // console.log('---------------------');

  if (activeSlideName !== slideName) {
    return null;
  }

  1. Your onNavigateSlideShow was using slideDirection instead of direction
 const onNavigateSlideShow = ({ slide, direction = 'forward' }) => {
    // const onNavigateSlideShow = ({ slide, slideDirection = 'forward' }) => {

    console.log('ccc', direction);
    setActiveSlide([slide, direction]);
  };
  1. I still can't get the directions to go in the right direction I think this is due to a race condition between the direction being set and when the animation is kicked off

If you click the back button before the animation completes it works as expected.

Here is where I got to: https://stackblitz.com/edit/react-framer-motion-slideshow-official-context-dftoab?file=src/SlideShow.js

Sorry that this is again not a complete answer. I think I am coming to the same conclusion as before that the two apis probably shouldn't be mixed. Especially due to edge cases like this one.

There have been a decent number of questions recently about context and AnimatePresence so made sandbox for most of the cases that I could think of: https://codesandbox.io/s/framer-motion-using-context-with-animate-presensce-nuj0m

Upvotes: 4

Related Questions