提问者:小点点

反应挂钩常数的UseMoom vs useState


使用React钩子定义一个计算(初始化)的常量可以通过两种功能等效的方式来执行。我不想讨论这方面的用例,但我只想说,在某些情况下,可以从初始道具或预期不会改变的状态(考虑路由数据、绑定调度等)中导出常量值。

首先,useState

const [calculatedConstant] = useState(calculateConstantFactory);

其次,usemo

const calculatedConstant = useMemo(calculateConstantFactory, []);

这两者在功能上似乎是等价的,但如果不阅读源代码,我不确定哪一个在性能或其他方面更好。

有人做过这方面的腿部工作吗?你会用哪一种?为什么?

此外,我知道有些人会对状态可以“视为常数”的假设感到畏缩。我不知道在那里该告诉你什么。但即使没有状态,我也可能希望在一个组件中定义一个完全没有状态的常量,例如,创建一个不改变的JSX块。

我可以在组件之外定义它,但它会消耗内存,即使在应用程序中的任何地方都没有实例化相关组件。要解决这个问题,我必须创建一个memonization函数,然后手动释放内部memonized状态。这是一个非常麻烦的东西钩给我们免费。

编辑:添加了本讨论中讨论的方法示例。https://codesandbox.io/s/cranky-platform-2b15l


共1个答案

匿名用户

您可以依赖useMemo作为性能优化,而不是语义保证

语义usemo不是正确的方法;你使用它的理由是错误的。因此,即使它现在按预期工作,但您正在错误地使用它,这可能会导致将来出现不可预测的行为。

useState仅当您不希望在计算值时阻止渲染时才是正确的选择。

如果在组件的第一次渲染中不需要该值,则可以同时使用useRefuseffect

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;

此选项将在设置值之前阻止组件渲染。

如果不希望阻止渲染,则需要将useStateuseffect一起使用:

const [calculated, setCalculated] = useState();

useEffect(() => {
  setCalculated(calculateConstantFactory())
}, [])

// use the value in calculated

基本上,如果需要组件重新渲染自身,请使用state。如果没有必要,请使用ref。