Transições de página simples e personalizáveis para os aplicativos Next.JS
Demo: https://next-page-transitions.now.sh/
Simplificando, facilita a adição de transições de página aos aplicativos construídos com o next.js. Pode funcionar com outras estruturas, mas foi projetado em torno do novo componente App e da maneira como o próximo.js lida com as páginas. Especificamente, ele resolve o problema de garantir que apenas um componente de uma página seja montado por vez e que a próxima página não seja montada até que a anterior tenha concluído sua animação de saída. Ele também possui suporte interno para mostrar um indicador de carregamento se o componente da página precisar carregar dados antes que ele possa ser mostrado.
Se você preferir aprender pelo exemplo, consulte o diretório examples para alguns aplicativos Next.js que demonstram como essa biblioteca pode ser usada.
Primeiro, instale o pacote:
npm install --save next-page-transitions
Em seguida, verifique se o seu aplicativo possui um componente App personalizado; Caso contrário, siga o exemplo no próximo.js leia para criar um. Em seguida, no método de renderização do seu App , envolva o Component da página em um componente PageTransition . Você também terá que definir suas próprias classes CSS que alcançam as animações de transição que você deseja. Para manter essa biblioteca simples e explicar a ampla variedade de maneiras pelas quais as pessoas produzem e consomem CSS, ela não oferece estilos internos e não tem uma opinião particular sobre como os estilos acabam na sua página. O exemplo abaixo tem uma transição simples que desaparece e saindo de páginas.
import App , { Container } from 'next/app'
import React from 'react'
import { PageTransition } from 'next-page-transitions'
export default class MyApp extends App {
static async getInitialProps ( { Component , router , ctx } ) {
let pageProps = { }
if ( Component . getInitialProps ) {
pageProps = await Component . getInitialProps ( ctx )
}
return { pageProps }
}
render ( ) {
const { Component , pageProps , router } = this . props
return (
< Container >
< PageTransition timeout = { 300 } classNames = "page-transition" >
< Component { ... pageProps } key = { router . route } />
</ PageTransition >
< style jsx global > { `
.page-transition-enter {
opacity: 0;
}
.page-transition-enter-active {
opacity: 1;
transition: opacity 300ms;
}
.page-transition-exit {
opacity: 1;
}
.page-transition-exit-active {
opacity: 0;
transition: opacity 300ms;
}
` } </ style >
</ Container >
)
}
} Quando você se move para uma nova página, o suporte key será alterado e o componente PageTransition detectará isso. Em vez de desmontar imediatamente a página, ele aplicará a classe page-transition-exit a uma embalagem em torno da página para inicializar a transição "Exit" e, em seguida, aplicará a classe page-transition-exit-active também para iniciar a transição. Isso é muito parecido com a maneira como a biblioteca de grupos de transição de reação faz as coisas. Depois que a página anterior foi animada, a nova página é montada e um par semelhante de classes .page-transition-enter e page-transition-enter-active será aplicada. Esse processo se repete toda vez que uma nova página é navegada.
NOTA : Nas versões anteriores de next-page-transitions , não foi necessário especificar o key suporte para os filhos da PageTransition . No entanto, para fazer com que a recarga do módulo quente funcione corretamente, era necessário tornar esse suporte necessário. Movendo foward, crianças que não especificam um suporte key desencadearão um aviso no console. No futuro, isso pode se tornar um erro de tempo de execução.
Suponha que você tenha uma página que precise fazer uma solicitação de rede antes que ela possa exibir seu conteúdo. Você pode fazer com que a página faça um girador de carregamento até que esteja pronto para ir, mas depois perde a bela animação de transição de página que passou todo esse tempo aperfeiçoando. Felizmente, esta biblioteca facilita a manipulação desse caso.
Se você adicionar uma propriedade estática pageTransitionDelayEnter = true ao seu componente de página, sua página será passada um suporte especial de retorno de chamada que você pode usar para indicar que tudo terminou de carregar. Enquanto isso, sua página será montada, mas a transição de Enter ainda não será iniciada e um indicador de carregamento de sua escolha será mostrado em seu lugar. Quando você chama o suporte de retorno de chamada, o girador de carregamento ficará oculto e sua página será animada no lugar! Por padrão, o retorno de chamada é passado através do Prop pageTransitionReadyToEnter , mas isso pode ser especificado definindo o suporte de nome loadingCallbackName em seu componente PageTransition .
Nota: verifique se o seu componente retorna null da função render() até terminar de carregar seu conteúdo e estar pronto para ser animado. Sua página ainda estará na árvore de componentes do React enquanto está carregando!
"Mas minhas solicitações de rede geralmente são rápidas!", Você dirá. "Eles geralmente levam apenas algumas centenas de milissegundos, e eu não quero exibir um indicador de carregamento na tela por um período tão curto de tempo!" Esta biblioteca também pode lidar com esse caso. Se você especificar um suporte loadingDelay , o indicador de carregamento não será mostrado até que muito tempo tenha decorrido. Se o seu componente estiver pronto para entrar antes disso, o indicador de carregamento nunca será mostrado, mantendo o UX limpo e ágil. No entanto, se o seu componente estiver demorando muito, o indicador de carregamento será mostrado até que seu componente esteja pronto.
"Isso soa como o conceito de espaço reservado daquela conversa sobre suspense. Aquele neste vídeo do YouTube". Sim, sim, sim! Essa foi a inspiração para esse recurso.
Aqui está um componente de exemplo que simula uma solicitação de rede com um tempo limite:
class About extends React . Component {
static pageTransitionDelayEnter = true
constructor ( props ) {
super ( props )
this . state = { loaded : false }
}
componentDidMount ( ) {
this . timeoutId = setTimeout ( ( ) => {
this . props . pageTransitionReadyToEnter ( )
this . setState ( { loaded : true } )
} , 2000 )
}
componentWillUnmount ( ) {
if ( this . timeoutId ) clearTimeout ( this . timeoutId )
}
render ( ) {
if ( ! this . state . loaded ) return null
return < div > Hello, world! </ div >
}
} Suponha por um momento que você tenha um componente Loader que renderize um bom indicador de carregamento giratório. Você terá que dizer ao componente PageTransition que deseja usar este componente e quanto tempo deseja esperar até mostrar o indicador de rede:
<PageTransition
timeout={300}
classNames="page-transition"
loadingComponent={<Loader />}
loadingDelay={500}
loadingTimeout={{
enter: 400,
exit: 0,
}}
loadingClassNames="loading-indicator"
>
<Component {...pageProps} key={router.route} />
</PageTransition>
Você também precisará adicionar estilos se quiser que o indicador de carregamento seja animado dentro/fora da tela. Se você deseja que ele apareça/desapareça sem qualquer animação, você pode adicionar loadingTimeout={0} e omitir a propriedade loadingClassNames .
Confira o aplicativo delayed-enter no Diretório examples para obter um exemplo completo de como isso é. A página "Sobre" ( pages/about.js ) aguardará 2 segundos antes de exibir seu conteúdo e, enquanto isso, o componente no components/Loader.js será exibido. Brinque com os vários atrasos para obter uma sensação mais profunda de como esse componente funciona.
PageTransition adereçosclassNames : Especifica os nomes de classe que serão aplicados ao invólucro da página para conduzir as animações de transição da página. Análogo ao componente CSSTranstition do classNames Prop do react-transition-group . No entanto, observe que apenas o formulário de string desse suporte é suportado no momento. Além disso, observe que esta biblioteca não possui um estado "aparece" separado; Somente as classes "Enter" e "Sair" são necessárias.tag : especifica a tag ou componente que será usado para renderizar o invólucro da página. Este elemento receberá o suporte classNames . Isso é útil se você deseja usar a marcação semântica, por exemplo, se você deseja renderizar o invólucro da página como main , ou se precisar personalizar ainda mais o estilo ou o comportamento do invólucro da página.timeout : especifica os tempos limite para as animações de transição da página. Análogo ao suporte timeout do componente CSSTranstition do react-transition-group .loadingComponent : um elemento react a ser mostrado enquantoloadingDelay : a duração para esperar antes de mostrar o indicador de carregamento, em milissegundos. Se uma página terminar o carregamento antes que essa duração tenha decorrida, o componente de carregamento nunca será mostrado. Padrão para 500ms.loadingCallbackName : Especifica o nome do suporte que sua página receberá para ligar quando for feito carregando. Padrão para pageTransitionReadyToEnterloadingTimeout : Análogo ao suporte timeout do componente CSSTranstition do react-transition-group . Se este suporte estiver definido como 0 , o indicador de carregamento não será animado para ligar/desativar a tela.loadingClassNames : Especifica os nomes de classe que serão aplicados ao componente de carregamento, se for especificado. Análogo ao componente CSSTranstition do classNames Prop do react-transition-group .monkeyPatchScrolling : Por padrão, o componente Link do próximo rolagem para a parte superior da página sempre que for clicada; Isso pode ter um efeito macio indesejável quando uma página está em transição. Se este suporte estiver definido como true quando o componente for montado, o window.scrollTo será repleto de macaco para que a rolagem programática possa ser desativada enquanto uma página estiver em transição. Padrões para falsos, uma vez que esse comportamento potencialmente superficial deve ser optado.skipInitialTransition : Especifica se a transição da página será omitida na primeira montagem. Se você deseja fazer transições apenas entre as páginas, não na carga da primeira página, defina skipInitialTransition como true . Por padrão, skipInitialTransition está definido como false .PRs são bem -vindos! Antes de trabalhar e enviar um PR, faça um problema descrevendo o recurso que você deseja criar. Pode estar fora do escopo deste projeto, ou um mantenedor já pode estar trabalhando nele.