如何获取Gatsby Link跳转目标,为Framer Motion条件渲染不同退出动画
解决方案
1. 重写LocationContext避免全量重渲染
核心逻辑是用useMemo包裹context值,路径变化后自动重置目标路径,从根源避免不必要的更新:
// src/context/locationContext.js import React, { createContext, useContext, useState, useMemo, useEffect } from "react" import { useLocation } from "@reach/router" // Gatsby内置路由 const LocationContext = createContext() export const LocationProvider = ({ children }) => { const currentLocation = useLocation() const [nextLocation, setNextLocation] = useState(null) // 当前路径变化后重置目标路径,避免影响后续转场 useEffect(() => { setNextLocation(null) }, [currentLocation.pathname]) // 缓存context值,仅依赖项变化时才更新 const contextValue = useMemo(() => ({ currentLocation, nextLocation, setNextLocation }), [currentLocation, nextLocation]) return ( <LocationContext.Provider value={contextValue}> {children} </LocationContext.Provider> ) } // 封装自定义hooks简化调用 export const useLocationContext = () => useContext(LocationContext)
2. 封装全局自定义Link组件
替代Gatsby原生Link,点击时先记录跳转目标路径再执行跳转:
// src/components/CustomLink.js import React from "react" import { Link as GatsbyLink } from "gatsby" import { useLocationContext } from "../context/locationContext" const CustomLink = ({ to, children, ...rest }) => { const { setNextLocation } = useLocationContext() const handleClick = (e) => { setNextLocation(to) // 执行传入的自定义点击事件 rest.onClick?.(e) } return ( <GatsbyLink to={to} {...rest} onClick={handleClick}> {children} </GatsbyLink> ) } export default CustomLink
全局替换所有用到Gatsby Link的位置,包括导航栏、项目页底部的下一个项目跳转链接。
3. 项目页条件渲染退出动画
在Project模板组件中根据跳转目标匹配不同的exit变体:
import { motion } from "framer-motion" import { useLocationContext } from "../context/locationContext" // 你的变体配置示例 const pageVariants = { enter: { opacity: 0 }, center: { opacity: 1 }, // 项目间转场的退出动画 projectExit: { opacity: 0, y: 20, transition: { duration: 0.4 } }, // 跳转非项目页的退出动画 globalExit: { opacity: 0, scale: 0.95, transition: { duration: 0.2 } } } const Project = ({ pageContext }) => { const { nextLocation } = useLocationContext() const project = Projects.find(({ id }) => id === pageContext.id) // 按照你自己的项目页路径规则修改匹配逻辑 const isToProjectPage = nextLocation?.startsWith('/works/') const activeExitVariant = isToProjectPage ? 'projectExit' : 'globalExit' return ( <Layout> {/* 给外层容器绑定motion属性 */} <motion.div initial="enter" animate="center" exit={activeExitVariant} variants={pageVariants} > <ProjectWrapper> {/* 原有页面内容保持不变 */} </ProjectWrapper> </motion.div> </Layout> ) }
额外优化
如果仍存在不必要的重渲染问题,可使用use-context-selector库替代原生useContext,按需订阅nextLocation字段,仅当该字段变化时才触发Project组件重渲染。
内容的提问来源于stack exchange,提问作者mdash
相关产品推荐
相关产品推荐

