1.1.2 • Published 1 year ago

inject-context v1.1.2

Weekly downloads
-
License
ISC
Repository
github
Last release
1 year ago

通过 selector 结合 React.memo 来解决 context 重渲染的性能问题

使用方式

npm install inject-context

单个 context

import React from 'react';
import injectContext from 'inject-context';

const MyContext = React.createContext({ count: 0 });

const App = props => {
  // context的count被注入到props中
  return <div>{props.count}</div>;
};

const Componnet = injectContext({
  context: MyContext,
  selector: s => ({ count: s.count }),
})(App);

多个 context

import React from 'react';
import injectContext from 'inject-context';

const MyContext1 = React.createContext({ count: 0 });
const MyContext2 = React.createContext({ count: 0 });

const App = props => {
  return <div>{props.count1 + props.count2}</div>;
};

const Componnet = injectContext([
  {
    context: MyContext1,
    selector: s => ({ count1: s.count }),
  },
  {
    context: MyContext2,
    selector: s => ({ count2: s.count }),
  },
])(App);

效果

组件重渲染,dom 会高亮,图中 count 会被改变,someString 不会被改变

源代码中 npm run demo 可以运行该 demo

20240410100632.gif

支持深度比较

inject-contex 使用 memo 来达到避免不必要渲染的目的,memo 默认的比较函数只对比第一层属性,也就是对于 memo 来说,下面两个 props 是不同的:

const prevProps = {
  obj: { key: 1 },
};
const newProps = {
  obj: { key: 1 },
};

inject-context 扩展了 memo 的默认比较函数,支持选择性的深度比较,如果选择的某个 context 状态想要深度比较的话,可以通过如下方式:

const InjectContextChild2 = injectContext<{
  someString: ContextValue['someString'];
}>({
  context: Context,
  selector: s => ({ obj: s.obj }),

  // selector返回的对象的键
  deepKeys: ['obj']
})(....);

指定deepKeys来告诉 inject-context 你需要深度比较的属性,值就是 selector 返回的对象的键名。

注意,不要滥用这个特性,深度比较带来的开销可能大于重渲染的开销。

TS 支持

props 类型提示

image.png

count 实际被注入到 props 里了,但是并没有良好的类型提示,可以通过给 inject-context 传泛型解决,它能接收两个泛型,第一个是注入的值的类型,第二个是原本 props 的类型。

image.png

selector 参数类型

默认的 selector 参数是 any,没有良好的类型提示

image.png

可以通过 inject-context 提供的 defineSelector 来提供类型提示。 用 defineSelector 包裹一下传入的 selector 属性即可。

image.png

写在最后

介绍文章

1.1.1

1 year ago

1.1.2

1 year ago

1.1.0

1 year ago

1.0.0

1 year ago