使用更新状态对象的回调-React.js



我有一个POSTAPI调用,我在单击按钮时进行调用。我们有一个大的状态对象,它作为POST调用的body发送。此状态对象会根据页面上不同的用户交互不断更新。

function QuotePreview(props) {
const [quoteDetails, setQuoteDetails] = useState({});
const [loadingCreateQuote, setLoadingCreateQuote] = useState(false);
useEffect(() => {
if(apiResponse?.content?.quotePreview?.quoteDetails) {
setQuoteDetails(apiResponse?.content?.quotePreview?.quoteDetails);
}
}, [apiResponse]);
const onGridUpdate = (data) => {
let subTotal = data.reduce((subTotal, {extendedPrice}) => subTotal + extendedPrice, 0);
subTotal = Math.round((subTotal + Number.EPSILON) * 100) / 100
setQuoteDetails((previousQuoteDetails) => ({
...previousQuoteDetails,
subTotal: subTotal,
Currency: currencySymbol,
items: data,
}));
};
const createQuote = async () => {
try {
setLoadingCreateQuote(true);
const result = await usPost(componentProp.quickQuoteEndpoint, quoteDetails);
if (result.data?.content) {
/** TODO: next steps with quoteId & confirmationId */
console.log(result.data.content);
}
return result.data;
} catch( error ) {
return error;
} finally {
setLoadingCreateQuote(false);
}
};
const handleQuickQuote = useCallback(createQuote, [quoteDetails, loadingCreateQuote]);
const handleQuickQuoteWithoutDeals = (e) => {
e.preventDefault();
// remove deal if present
if (quoteDetails.hasOwnProperty("deal")) {
delete quoteDetails.deal;
}
handleQuickQuote();
}
const generalInfoChange = (generalInformation) =>{
setQuoteDetails((previousQuoteDetails) => (
{
...previousQuoteDetails,
tier: generalInformation.tier,
}
));
}
const endUserInfoChange = (endUserlInformation) =>{
setQuoteDetails((previousQuoteDetails) => (
{
...previousQuoteDetails,
endUser: endUserlInformation,
}
));
}
return (
<div className="cmp-quote-preview">
{/* child components [handleQuickQuote will be passed down] */}
</div>
);
}

当调用handleQuickQuoteWithoutDeals函数时,我正在从对象中删除一个键。但是我想立即用更新的对象调用API。我在这里直接删除了deal密钥,但如果我以不可变的方式删除,那么下面的API调用不会考虑更新的对象,而是考虑前一个对象。

我找到的解决这个问题的唯一方法是引入一个新状态,并在单击时更新它,然后使用useEffect钩子来跟踪这个状态,以便在它更改时进行API调用。使用这种方法,它以一种奇怪的方式工作,在初始加载和其他奇怪行为时,它一直调用API。

有更干净的方法吗?

目前尚不清楚任何子级将如何调用handleQuickQuote回调,但如果您需要在回调范围内关闭一个";复制";对于quoteDetails的详细信息,我建议进行以下小型重构,以允许该父组件使用原始createQuote函数,同时子组件接收包含当前quoteDetails的内存化回调。

使用quoteDetails作为参数:

const createQuote = async (quoteDetails) => {
try {
setLoadingCreateQuote(true);
const result = await usPost(componentProp.quickQuoteEndpoint, quoteDetails);
if (result.data?.content) {
/** TODO: next steps with quoteId & confirmationId */
console.log(result.data.content);
}
return result.data;
} catch( error ) {
return error;
} finally {
setLoadingCreateQuote(false);
}
};

记忆一个";匿名的";传入quoteDetails值的回调:

const handleQuickQuote = useCallback(
() => createQuote(quoteDetails),
[quoteDetails]
);

创建quoteDetails的浅层副本,删除属性,并调用createQuote:

const handleQuickQuoteWithoutDeals = (e) => {
e.preventDefault();
const quoteDetailsCopy = { ...quoteDetails };
// remove deal if present
if (quoteDetailsCopy.hasOwnProperty("deal")) {
delete quoteDetailsCopy.deal;
}
createQuote(quoteDetailsCopy);
}