gpt4 book ai didi

javascript - 创建自定义钩子(Hook)来覆盖 useState() 钩子(Hook)并合并对象属性(React JS)

转载 作者:行者123 更新时间:2023-11-30 23:58:00 26 4
gpt4 key购买 nike

好的,所以我正在尝试创建一个自定义 Hook “useObjectState”,以便我可以更好地利用功能组件中的对象,并且能够合并对象 Prop 。这是我到目前为止所拥有的:

  const useObjectState = initialObject => {
const [obj, setObj] = useState(initialObject);

const setMergedObj = x => {
setObj(obj => ({ ...obj, ...x }));
};

return [obj, setMergedObj];
};

现在不要调用 useState() setter 函数,如下所示:

  setObject(obj => ({...obj, prop1: newValue}))

我可以这样调用它:

   setObject({prop1: newValue});

它会很好地合并。我遇到的问题是批处理多个调用,如果我不使用自定义 Hook ,那么这些调用将批处理为单独的调用并连续执行:

setObject(obj => ({...obj, prop1: oldVal + 1}));
setObject(obj => ({...obj, prop1: oldVal + 1}));
setObject(obj => ({...obj, prop1: oldVal + 1}));

但是使用我编写的自定义 Hook 似乎不起作用,最后一个调用将覆盖前两个:

setObject({prop1: oldVal + 1});
setObject({prop1: oldVal + 1});
setObject({prop1: oldVal + 1}); //only this function works, the other 2 are overwritten

知道如何解决这个问题吗?

示例代码(如某人所问)

import React, { useState } from "react";
import "./App.css";

const useObjectState = initialObject => {
const [obj, setObj] = useState(initialObject);

const setMergedObj = x => {
setObj(obj => ({ ...obj, ...x }));
};

return [obj, setMergedObj];
};

function App() {
let [obj, setObj] = useObjectState({
num1: 1,
num2: 10
});

let [obj2, setObj2] = useState({
num1: 1,
num2: 10
});

const increment = x => {
setObj({ num1: obj.num1 + 1 });
setObj({ num1: obj.num1 + 1 });
setObj({ num1: obj.num1 + 1 }); //this will override the other 2

setObj({ num2: obj.num2 + 10 });

setObj2(obj2 => ({ ...obj2, num1: obj2.num1 + 1 }));
setObj2(obj2 => ({ ...obj2, num1: obj2.num1 + 1 }));
setObj2(obj2 => ({ ...obj2, num1: obj2.num1 + 1 })); //these 3 functions will add 3 at a time to obj2.num1

setObj2(obj2 => ({ ...obj2, num2: obj2.num2 + 10 }));
};
const decrement = () => {
setObj({ num1: obj.num1 - 1 });
setObj({ num2: obj.num2 - 10 });
};

return (
<div className="App">
<button onClick={() => increment(1)}>+</button>
<div>{obj.num1}</div>
<div>{obj.num2}</div>
<div>{obj2.num1}</div>
<div>{obj2.num2}</div>

<button onClick={() => decrement()}>-</button>
</div>
);
}

export default App;

最佳答案

我看到的一个问题是您正在传递对原始对象的引用:

setObj({num1: obj.num1 + 1});

setObj() 的参数无法引用内部更新的状态,因此 obj.num1 将始终引用钩子(Hook)返回的原始值。

您可能需要考虑允许您的钩子(Hook)接收函数,就像原始 useState 那样,并重写您的钩子(Hook),如下所示:

const setMergedObj = x => {
typeof x === "function"
? setObj(obj => ({...obj, ...x(obj)}))
: setObj(obj => ({...obj, ...x}))
;
};

然后像这样使用它

setObj(obj => ({num1: obj.num1 + 1}));

如果您从其他地方更新日期,我可以看到仅对象版本仍然相关,但您将需要功能版本来引用现有状态。

关于javascript - 创建自定义钩子(Hook)来覆盖 useState() 钩子(Hook)并合并对象属性(React JS),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60921604/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com