计算自定义钩子中的初始值



在我的反应应用程序中,我有一个自定义钩子useDataObject(),它根据另一个钩子的值计算一个对象,例如useScreenWidth().我的问题是,我不知道在哪里放置计算逻辑,所以对象在第一次返回时立即准备就绪:


function useScreenWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return width;
}
function useDataObject() {
const width = useScreenWidth();
const [dataObject, setDataObject] = useState();
useEffect(() => {
// Some logic that creates dataObject from width
const dataObject = {
firstValue: 2 * width,
secondValue: width + 10
};
setDataObject(dataObject);
}, [width]);
return dataObject;
}
export default function App() {
const dataObject = useDataObject();
// Can I get rid of this check?
// Currently needed to prevent "Can not read property firstValue of undefined
if (!dataObject) {
return null;
}
return (
<>
<div>Data object first value: {dataObject.firstValue}</div>
<div>Data object second value: {dataObject.secondValue}</div>
</>
);
}

查看此沙盒

因为useDataObject没有初始状态,我需要等待第一个useEffect完成,直到我得到一个有效的dataObject。这意味着我需要在调用useDataObject()后始终包含一个空检查。

在第一次返回之前执行计算逻辑的最佳方法是什么,然后在每次宽度更改时执行useDataObject()

我尝试的一种方法是创建一个执行计算的内部函数:

function useDataObject() {
const width = useScreenWidth();
const [dataObject, setDataObject] = useState(calculateDataObject());
function calculateDataObject() {
// Some logic that creates dataObject from width
const dataObject = {
firstValue: 2 * width,
secondValue: width + 10
};
return dataObject;
}
useEffect(() => {
setDataObject(calculateDataObject());
}, [width, calculateDataObject]);
return dataObject;
}

但这看起来非常笨拙和混乱。它还给了我一个 linting 错误,告诉我应该使用useCallback().难道没有更直接的方法吗? 谢谢!

回答我自己的问题。我发现使用useMemo()钩子(请参阅文档(而不是useState()+useEffect()是我的方案的可能解决方案:

function useDataObject() {
const width = useScreenWidth();
return useMemo(() => {
// Do some calculation with width
const dataObject = {
firstValue: 2 * width,
secondValue: width + 10
};
return dataObject;
}, [width]);
}

代码沙箱的完整示例

  • 挂钩会立即返回计算出的dataObject
  • 每次更改[width]时,都会重做计算并返回新值。
  • 没有代码重复或执行得太频繁。

我不能保证没有更好的解决方案,但就我的目的而言,它完全符合我的需求。 (当然,也可以将useScreenWidth钩集成到useDataObject钩中。但是在我的项目中,我需要单独useScreenWidth

相关内容

  • 没有找到相关文章

最新更新