inject-context
v1.1.2
Published
Avoid unnecessary re-rendering of components caused by changes in context value
Downloads
8
Readme
通过 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
支持深度比较
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 类型提示
count 实际被注入到 props 里了,但是并没有良好的类型提示,可以通过给 inject-context 传泛型解决,它能接收两个泛型,第一个是注入的值的类型,第二个是原本 props 的类型。
selector 参数类型
默认的 selector 参数是 any,没有良好的类型提示
可以通过 inject-context 提供的 defineSelector
来提供类型提示。
用 defineSelector
包裹一下传入的 selector 属性即可。