我有一些狀態變數會在某個時間點發生變化。我想知道處理如此大量的輸入變數的正確方法是什么。我在 Vue.js 中使用了相同的代碼,雙向資料系結對我來說效果很好。處理以下變數的適當方法是什么?
data() {
return {
valid: false,
showDialog: true,
showFullLoading: false,
isImage: false,
product: {
name_en: "",
name_ar: "",
category: "",
subcategory: "",
description_en: "",
description_ar: "",
meta_title: "",
meta_description: "",
meta_keywords: "",
price: 0.0,
showSale: false,
sale: 0.0,
image: "",
saleAfterStock: false,
stock: 10
},
images: [
{ image: null, isImage: false, id: shortid.generate() },
{ image: null, isImage: false, id: shortid.generate() },
{ image: null, isImage: false, id: shortid.generate() },
{ image: null, isImage: false, id: shortid.generate() }
],
attributes: [],
defaultVariants: [],
dataWeightClass: ["Gram", "Kilo Gram", "Pound"],
dataDimensionClass: ["Centimeter", "Inch"],
showAttributeDialog: false,
sizeGuide: false,
sizeGuides: [],
attribute: {
title_en: "",
title_ar: "",
description_en: "",
description_ar: "",
image: null,
isImage: false
},
subcategories: [],
options: [],
variantsHeaders: [
{ text: "Variant", value: "name" },
{ text: "Price", value: "price" },
{ text: "Stock", value: "quantity" },
{ text: "Visibility", value: "visibility" }
],
defaultVariantId: "",
defaultPreviewId: ""
};
},
這是 vue 中的資料物件。我想將這些資料物件轉換為反應狀態。謝謝。
uj5u.com熱心網友回復:
你說過你要寫一個函陣列件。在函陣列件中,存盤狀態的常用方法(在 React 本身中)是useState
和useReducer
:
useState
-回傳一個有狀態的值,以及一個更新它的函式。
useReducer
-接受一個 reducer 型別
(state, action) => newState
,并回傳與方法配對的當前狀態dispatch
。(如果您熟悉 Redux,那么您已經知道它是如何作業的。)
在 React 之外,還有像Redux(帶有React 系結)、Mobx和其他提供高級狀態管理的工具。
堅持 React 中的內容,如果你的狀態物件的各個部分相對于彼此發生變化,你可能想要useReducer
. 如果它們相當不同,您可能想要useState
(盡管有些人從不使用useReducer
,而其他人從不使用useState
)。從useReducer
檔案中:
useReducer
useState
當您具有涉及多個子值的復雜狀態邏輯或下一個狀態取決于前一個狀態時,通常更可取。useReducer
還可以讓您優化觸發深度更新的組件的性能,因為您可以傳遞dispatch
而不是回呼。
useState
使用useState
,您可以擁有像資料物件一樣的巨石狀態物件,或者您可以將其分解為單獨的部分。我會默認將其分解為多個部分,并且僅在必要時才使用巨石物件,尤其是因為更新更簡單。(盡管如此,您的資料物件相對平坦,這意味著更新并不難。)
這可能是這樣的:
function MyComponent(props) {
const [valid, setValid] = useState(false);
const [showDialog, setShowDialog] = useState(true);
// ...
const [product, setProduct] = useState({
name_en: "",
name_ar: "",
category: "",
subcategory: "",
description_en: "",
description_ar: "",
meta_title: "",
meta_description: "",
meta_keywords: "",
price: 0.0,
showSale: false,
sale: 0.0,
image: "",
saleAfterStock: false,
stock: 10,
});
// ...
const [images, setImages] = useState([
{ image: null, isImage: false, id: shortid.generate() },
{ image: null, isImage: false, id: shortid.generate() },
{ image: null, isImage: false, id: shortid.generate() },
{ image: null, isImage: false, id: shortid.generate() },
]);
// ...
}
您可以在組件外部定義這些初始值,這樣您就不會不必要地重新創建物件和陣列,并且為了代碼清晰。例如,如果您的現有資料物件為defaults
,則上面可能是:
const defaults = { /*...*/ };
function MyComponent(props) {
const [valid, setValid] = useState(defaults.valid);
const [showDialog, setShowDialog] = useState(defaults.showDialog);
// ...
const [product, setProduct] = useState(defaults.product);
// ...
const [images, setImages] = useState(defaults.images);
// ...
}
無論哪種方式,您都可以通過呼叫它們的 setter 來更新這些狀態成員。對于valid
和其他簡單的原語,它非常簡單:
setValid(newValue);
...或者,如果您在設定新值時使用舊值(如切換),請使用回呼表單,以便確保獲得最新的狀態資訊:
setValid((oldValue) => !oldValue);
對于物件和陣列,它更復雜。您必須使用所需的更改創建一個新物件或陣列。例如,要更新product
's category
:
setProduct((oldProduct) => { ...oldProduct, category: "new category" });
請注意我們如何復制舊產品物件,然后對其應用更新。副本可能很淺(這是傳播語法所做的)。
images
要使用說明要更新id
哪個影像的變數進行更新,并且(假設)您要設定isImage
為true
:
setImages((oldImages) => oldImages.map((image) => {
if (image.id === id) {
return { ...image, isImage: true }; // Or whatever change it is
}
return image;
}));
再次注意,我們不僅為現有陣列分配了一個新的影像物件,我們還創建了一個新陣列(在本例中為 via map
)。
如果你使用了巨石狀態物件,像這樣:
function MyComponent(props) {
const [state, setState] = useState(defaults);
// ...
}
...然后更新(比如說)images
變得有點困難,雖然你的狀態物件又是相當淺的,所以它不是那么糟糕:
setState((oldState) => ({
...oldState,
images: oldState.images.map((image) => {
if (image.id === id) {
return { ...image, isImage: true }; // Or whatever change it is
}
return image;
})
}));
無論哪種方式(個人或巨石)的關鍵是必須復制作為您正在更改的內容(直接或間接)的容器的任何物件或陣列。只是對于一個巨石結構,你最終會做更多的副本,因為所有東西都在一個容器中。
useReducer
使用useReducer
,您再次可以選擇該函式更新的單個巨石狀態物件dispatch
(通過您的reducer
函式),或者單獨的,每個都有自己的dispatch
和(可能)reducer
函式。使用useReducer
,擁有大型狀態物件更為常見,因為主要用例之一是大型結構,其中不同部分可以通過單個操作進行更新。這可能意味著巨石,或者只是更大的塊等。
主要區別在于組件中的代碼通過 發送“動作” dispatch
,然后是dispatch
您撰寫的函式中的代碼對狀態物件進行更新并回傳新的。
假設您useReducer
與巨石物件一起使用:
function MyComponent(props) {
const [state, dispatch] = useReducer(reducer, defaults);
// ...
}
你reducer
可能看起來像這樣:
function reducer(state, action) {
const { type, ...actionParams } = action;
switch (type) {
case "update-image":
const { id, ...updates } = actionParams;
return {
...state,
images: state.images.map((image) => {
if (image.id === id) {
return { ...image, ...updates };
}
return image;
})
};
// ...other actions...
}
}
然后在您的組件中,您可以執行以下操作,而不是setImages
本節中顯示的呼叫useState
:
dispatch({ type: "update-image", id, isImage: true });
或類似的(有很多不同的方法來撰寫 reducer 函式)。
相同的規則適用于狀態更新您的reducer
回傳值作為useState
設定器:必須復制包含您正在更新的內容的任何物件或陣列。所以在這個例子中,復制整個狀態物件、images
陣列和我們正在更新的影像物件。與 一樣useState
,如果你使用更多的個人useReducer
s,你會做更少的復制。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/508305.html
標籤:javascript 反应 状态