使用React钩子定义一个计算(初始化)的常量可以通过两种功能等效的方式来执行。我不想讨论这方面的用例,但我只想说,在某些情况下,可以从初始道具或预期不会改变的状态(考虑路由数据、绑定调度等)中导出常量值。
首先,useState
const [calculatedConstant] = useState(calculateConstantFactory);
其次,usemo
const calculatedConstant = useMemo(calculateConstantFactory, []);
这两者在功能上似乎是等价的,但如果不阅读源代码,我不确定哪一个在性能或其他方面更好。
有人做过这方面的腿部工作吗?你会用哪一种?为什么?
此外,我知道有些人会对状态可以“视为常数”的假设感到畏缩。我不知道在那里该告诉你什么。但即使没有状态,我也可能希望在一个组件中定义一个完全没有状态的常量,例如,创建一个不改变的JSX块。
我可以在组件之外定义它,但它会消耗内存,即使在应用程序中的任何地方都没有实例化相关组件。要解决这个问题,我必须创建一个memonization函数,然后手动释放内部memonized状态。这是一个非常麻烦的东西钩给我们免费。
编辑:添加了本讨论中讨论的方法示例。https://codesandbox.io/s/cranky-platform-2b15l
您可以依赖useMemo作为性能优化,而不是语义保证
语义usemo
不是正确的方法;你使用它的理由是错误的。因此,即使它现在按预期工作,但您正在错误地使用它,这可能会导致将来出现不可预测的行为。
useState
仅当您不希望在计算值时阻止渲染时才是正确的选择。
如果在组件的第一次渲染中不需要该值,则可以同时使用useRef
和useffect
:
const calculatedConstant = useRef(null);
useEffect(() => {
calculatedConstant.current = calculateConstantFactory()
}, [])
// use the value in calcaulatedConstant.current
这与在componentDidMount
中初始化实例字段相同。当工厂功能运行时,它不会阻止您的布局/绘制。就性能而言,我怀疑任何基准都不会显示出显著的差异。
问题是在初始化ref之后,组件不会更新以反映该值(这是ref的全部用途)。
如果绝对需要在组件的第一次渲染中使用该值,可以执行以下操作:
const calculatedConstant = useRef(null);
if (!calculatedConstant.current) {
calculatedConstant.current = calculateConstantFactory();
}
// use the value in calculatedConstant.current;
此选项将在设置值之前阻止组件渲染。
如果不希望阻止渲染,则需要将useState
与useffect
一起使用:
const [calculated, setCalculated] = useState();
useEffect(() => {
setCalculated(calculateConstantFactory())
}, [])
// use the value in calculated
基本上,如果需要组件重新渲染自身,请使用state。如果没有必要,请使用ref。