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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@654356282/react-keepalive

v2.0.0

Published

React Keepalive Component

Downloads

16

Readme

ReactKeepAlive

为组件提供 keepalive 能力,无数据断层!不操作 dom 节点!使用 suspense 作 keepalive!

缓存策略:优先使用 children 的 key 值作为缓存的 key,如果不存在 key 则使用 children 的 type

Keepalive Props

excludes: []|Regexp|(key: string|number)=>boolean: 传入不需要缓存的组件的key,或者可传入正则表达式或函数

includes: []|Regexp|(key: string|number)=>boolean: 传入需要换的的组件的key,或者可传入正则表达式或函数

Ref

type KeepAliveRef = {
  controller: {
    // 丢弃缓存的组件
    drop: (name: Key) => void;
  } | null;
};

Hooks

useActived: 组件从初次渲染或者从隐藏切换到显示时激活 useUnactived: 组件销毁或者从显示切换到隐藏时激活 useController: 获取refcontroller对象

usage

组件缓存

import { KeepAlive, useActived, useUnactived } from "@654356282/react-keepalive";
import React, { useState } from "react";

const Comp1 = () => {
  const [count, setCount] = useState(0);

  useActived(() => {
    console.log("Comp1 is actived");
  });

  useUnactived(() => {
    console.log("Comp1 is unactived");
  });

  return (
    <div>
      Comp1
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
};

const Comp2 = () => {
  const [count, setCount] = useState(0);

  useActived(() => {
    console.log("Comp2 is actived");
  });

  useUnactived(() => {
    console.log("Comp2 is unactived");
  });

  return (
    <div>
      Comp2
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
};

// 此时keepalive中缓存的key值为Comp1和Comp2
function App() {
  const [toggle, setToggle] = useState(false);

  return (
    <div>
      <KeepAlive>{toggle ? <Comp1 /> : <Comp2 />}</KeepAlive>
      <button onClick={() => setToggle(!toggle)}>change</button>
    </div>
  );
}

react-router集成,使用createBrowserRouter

import { ReactElement, useState } from "react";
import { KeepAlive, useActived, useUnactived } from "@654356282/react-keepalive";
import { RouterProvider, createBrowserRouter, NavLink } from "react-router-dom";
import React from "react";

function KeepAliveWrapper(props: { children: ReactElement }) {
  return <KeepAlive excludes={["/home"]}>{props.children}</KeepAlive>;
}

const router = createBrowserRouter([
  {
    path: "/",
    element: (
      <KeepAliveWrapper>
        <Root key="/" />
      </KeepAliveWrapper>
    ),
  },
  {
    path: "/home",
    element: (
      <KeepAliveWrapper>
        <Home key="/home" />
      </KeepAliveWrapper>
    ),
  },
]);

function Root() {
  const [count, setCount] = useState(0);

  useActived(() => {
    console.log("Root is actived");
  });

  useUnactived(() => {
    console.log("Root is unactived");
  });

  return (
    <div>
      <div>Root</div>
      <div>
        {count}
        <button onClick={() => setCount(count + 1)}>+1</button>
      </div>
      <NavLink to={"/home"}>跳转</NavLink>
    </div>
  );
}

function Home() {
  const [count, setCount] = useState(0);

  useActived(() => {
    console.log("Home is actived");
  });

  useUnactived(() => {
    console.log("Home is unactived");
  });

  return (
    <div>
      <div>Home</div>
      <div>
        {count}
        <button onClick={() => setCount(count + 1)}>+1</button>
      </div>
      <NavLink to={"/"} replace>
        跳转
      </NavLink>
    </div>
  );
}

export default function App() {
  return <RouterProvider router={router} />;
}

使用嵌套式路由

import React, { ReactElement, useState } from "react";
import {
  BrowserRouter,
  NavLink,
  Outlet,
  Route,
  Routes,
} from "react-router-dom";
import { KeepAlive, useActived, useUnactived } from "@654356282/react-keepalive";

function wrapKeepAlive(children: ReactElement) {
  return <KeepAlive includes={/^\/home.*/}>{children}</KeepAlive>;
}

const Home = () => {
  useActived(() => {
    console.log("home actived");
  });

  useUnactived(() => {
    console.log("home unactived");
  });
  const [count, setCount] = useState(0);

  return (
    <div>
      <div>home--{count}</div>
      <button onClick={() => setCount(count + 1)}>+1</button>
      <NavLink to="/user">跳转 user</NavLink>
      <Outlet />
    </div>
  );
};

const HomeSon = () => {
  const [count, setCount] = useState(0);

  useActived(() => {
    console.log("home son actived");
  });

  useUnactived(() => {
    console.log("home son unactived");
  });

  return (
    <div>
      <div>home son--{count}</div>
      <button onClick={() => setCount(count + 1)}>son + 1</button>
      <NavLink to="/user/son">跳转user son</NavLink>
    </div>
  );
};

const User = () => {
  const [count, setCount] = useState(0);
  useActived(() => {
    console.log("user actived");
  });

  useUnactived(() => {
    console.log("user unactived");
  });

  return (
    <div>
      <div>user--{count}</div>
      <button onClick={() => setCount(count + 1)}>+1</button>
      <NavLink to="/home">跳转 home</NavLink>
      <Outlet />
    </div>
  );
};

const UserSon = () => {
  const [count, setCount] = useState(0);

  useActived(() => {
    console.log("user son actived");
  });

  useUnactived(() => {
    console.log("user son unactived");
  });

  return (
    <div>
      <div>user son--{count}</div>
      <button onClick={() => setCount(count + 1)}>+1</button>
      <NavLink to="/home/son">跳转home son</NavLink>
    </div>
  );
};

const App = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/home" element={wrapKeepAlive(<Home key="/home" />)}>
          <Route
            path="son"
            element={wrapKeepAlive(<HomeSon key="/home/son"></HomeSon>)}
          />
        </Route>
        <Route path="/user" element={wrapKeepAlive(<User key="/user" />)}>
          <Route
            path="son"
            element={wrapKeepAlive(<UserSon key="/user/son" />)}
          />
        </Route>
      </Routes>
    </BrowserRouter>
  );
};

export default App;

tips: 如果需要缓存子路由,请保证父级路由需要keepAlive