React-spring: useTransition with react-router to cross-fade page transitions

Created on 16 Jan 2019  路  5Comments  路  Source: pmndrs/react-spring

Since the useTransition hook can't be created within the render function I don't know how to pass Switch and Route from react-router-dom as items to useTransition.

First, I just used Transition but this was messy and didn't properly work because I need both react-spring and react-spring/hooks to be imported plus renaming the second animated (e.g. animated as animatedHooks) since they couldn't be mixed. I got also some error messages and the entire thing broke.

Is there an (easy) way to pair useTransition with react-router?

question

Most helpful comment

oh yeah, useTransition has a slightly difference signature: useTransition(items, keys, config), that has to be reflected by typing still.

All 5 comments

I prepared a Codesandbox at https://codesandbox.io/s/k02r79o09v where I set up some extra array for the pages to use later. However, I got lost along the track and hacked something together I couldn't get to work. There must be an easier way ...

@jas99 nice! i didn't know about routercontext! i cleaned it up a little, this should go into examples. tanks alot!

https://codesandbox.io/s/jp1wr1867w

@drcmda Glad you liked it.
I actually use useRouter internally which will be comming in next release. Do mindd routercontext is on beta branch for now.

import { useContext } from "react"
import { RouteComponentProps } from "react-router-dom"
import * as H from "history"
import { StaticContext } from "react-router"

const RouterContext = require( "react-router-dom" ).__RouterContext

// FIXME:  use official API when https://github.com/ReactTraining/react-router/pull/6453 merged

export function useRouter<
    Params extends { [K in keyof Params]?: string } = {},
    C extends StaticContext = StaticContext,
    S = H.LocationState
> ()
{
    return useContext( RouterContext ) as RouteComponentProps<Params, C, S>
}

You can include this also in example.

Let me show you how I use it for internal project (The react hooks way :wink:) Offcourse its matter of preference. :smile:

import React, { SFC, useEffect, useState, CSSProperties, Component } from "react"
import { Home } from "./view/home/Home"
import { animated } from "react-spring/hooks"
const { useTransition } = require( "react-spring/hooks" )
import { useRouter } from "../lib/useRouter"
import { TitleRedBlack } from "../components/text/TitleRedBlack"
import { Menu } from "../components/Menu"

const pages = {
    home: ( <Home /> ),
    title: ( <TitleRedBlack
        title="Data solutions"
        subtitle="that work"
    />
    )
}

const Layout = () =>
{
    const { location, match, history } = useRouter()
    const [page, setPage] = useState<keyof typeof pages>( "home" )

    useEffect( () =>
    {
        const page = location.pathname.replace( /\//g, "" )
        if ( page in pages )
        {
            setPage( page as keyof typeof pages )
        }
        else
        {
            setPage( "home" )
        }
    }, [location.pathname] )

    const transitions = useTransition(
        page,
        ( key: any ) => key,
        {
            config: { duration: 300 },
            from: { opacity: 0, transform: "translate(100%,0)" },
            enter: { opacity: 1, transform: "translate(0%,0)" },
            leave: { opacity: 0, transform: "translate(-50%,0)" },
        }
    )

    return (
        <div>
            <Menu />
            {
                transitions.map( ( { item, key, props } ) =>
                {
                    const page = pages[item]
                    const style: CSSProperties = {
                        ...props,
                        position: "absolute"
                    }
                    return (
                        <animated.div key={ key } style={ style }  >
                            { page }
                        </animated.div>
                    )
                }
                )
            }
        </div>
    )
}

PS: Using beta version of react-spring; types for useTransition are broken thats why using require for now
@Jessidhia :pray: :smile:

oh yeah, useTransition has a slightly difference signature: useTransition(items, keys, config), that has to be reflected by typing still.

Was this page helpful?
0 / 5 - 0 ratings