npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

rc-bfcache

v0.1.0

Published

实现类似浏览器前进后退缓存策略的 React 组件状态缓存方案

Readme

rc-bfcache

浏览器使用 前进后退缓存(Back/forward cache) 优化了用户浏览网站的导航体验,但是这只是针对不同页面间的前进后退,对于 spa 应用是不起作用的,但是很多 spa 应用也会有类似的缓存需求,实现这类需求往往会入侵业务代码,从而造成混乱。

为此,rc-bfcache 提供了一个 history 扩展函数,维护了一份与浏览器同步的路由栈信息,为组件状态缓存的自动清除提供判断依据。使用者在对 history 对象进行能力扩展后,只需要调用与 useState 类似的 hook 方法 — useRouteState,即可让组件状态获得缓存能力,而无需关心缓存清空逻辑。

当然,这一切的前提是:你所使用的路由框架(如: react-router)依赖于 history 这个库,同时允许传入自定义的 history 对象。

安装

pnpm install rc-bfcache

使用

1、扩展 history 对象

使用 enhanceHistory 扩展 history 对象的能力。

import React from 'react';
import { 
  unstable_HistoryRouter as HistoryRouter,
  HistoryRouterProps
} from 'react-router-dom';
import { enhanceHistory } from 'rc-bfcache'
import { createBrowserHistory } from 'history';

const myHistory = enhanceHistory(createBrowserHistory({ window }))

export const CustomRouter = (props: HistoryRouterProps) => (
  <HistoryRouter {...props} history={myHistory} />
);

注意:请保证项目依赖的 history 软件包版本与 react-router 的保持一致。

2、使用组件状态缓存


type SetRefState<S> = (
  /** 待更新的值 */
  state: S | ((s: S) => S),
  /** 更新值的时候,阻止重新渲染 */
  preventUpdate?: boolean
) => void;
function useBfCache<T>(init: T | (() => T), suffix?: string): [T, SetRefState<T>]

useBfCache 的使用于 useState类似, 区别在于它可以传入第二个参数,用于标识页面缓存的 key 值,只要确保在当前页面下是唯一的即可,因为当前 hook 状态缓存的 ID 是当前页面ID与key值的组合。

import React, { useEffect } from 'react'
import { useBfCache } from 'rc-bfcache';

const DataContainer = () => {
  // 浏览器前进后退过程中
  // 组件会使用缓存中的状态进行初始化
  const [data, setData] = useBfCache(null, 'data');
  useEffect(() => {
    if (!data) {
      fetchData().then(data => setData(data))
    }
  }, []);
  return (<DataRender data={data} />)
}

获取路由动作

useRouteAction

在组件内获取路由动作,支持传入回调函数,该回调函数仅会在首次渲染前执行一次。

import { useRouteAction, withRouteAction } from 'rc-bfcache';
export const RouteComponent = () => {
  const action = useRouteAction((action) => {
    switch (action) {
      case 'PUSH': /* do something */ break;
      case 'POP': /* do something */ break;
      case 'REPLACE': /* do something */ break;
    }
  });
  console.log(action);
  return (<>{/* */}</>)
}

withRouteAction

使用高阶函数将路由动作传给目标组件的 props.routeAction 属性。支持传入回调函数,如果回调函数返回值为 Promise 对象,那么在 Promise 对象 resolve 之前,组件默认只渲染fallback 参数(默认值为null),resolve 之后渲染目标组件。

import { withRouteAction } from 'rc-bfcache';
import { MyComponent } from './components';

export const RouteComponent = withRouteAction(MyComponent, {
  callback(action) {
    switch (action) {
      case 'PUSH': /* do something */ break;
      case 'POP': /* do something */ break;
      case 'REPLACE': /* do something */ break;
    }
  },
  fallback: "loading..."
})

完整 API 文档地址