![](/img/trans.png)
[英]how to send data From one component to another components with context in react?
[英]Send information from multiple children components to one parent component in React
我有一個父組件呈現子組件subtotals
的total
。
function Total({ products }) {
const [total, setTotal] = useState(0);
const handleChildToParent = (subtotal) => {
setTotal(total + subtotal);
};
return (
<div>
{products.map((product) => (
<Subtotal product={product} childToParent={handleChildToParent} />
))}
<span>Total: {total}</span>
</div>
);
}
每個Subtotal
組件都包含一個項目的價格,並根據用戶選擇的單位數量計算小計。
function Subtotal({ product, childToParent }) {
const [units, setUnits] = useState(0);
const handleInputChange = (value) => {
setUnits(value);
childToParent(value * product.price);
};
return (
<div>
<input
type="number"
min={1}
onChange={(e) => handleInputChange(e.target.value)}
value={units}
/>
<span>units * product price: {units * product.price}</span>
</div>
);
}
我的目標是根據子組件的信息在父組件中進行動態總計。 例如:用戶選擇兩個價格為 100 美元的項目,三個價格為 12 美元,父組件應顯示為 236 美元,子組件應顯示第一個項目為 200 美元($100x2),第一個項目為 36 美元($12x3)第二個項目(這是我目前擁有的),如果用戶對第一個項目改變主意,而不是兩個只想要一個,總價格應該更新為 136 美元。 當我嘗試減去一個項目時,我被卡住了。 我嘗試設置項目的初始總和並將 useEffect 與 total 一起使用,但我無法找到解決方案。 任何幫助將不勝感激,我實際上不知道這是否真的可以使用組件之間的子到父通信。
這是一個經典示例,您應該將 state 從“小計”組件中“提升”到父組件中。
通常,多個組件需要反映相同的變化數據。 我們建議將共享的 state 提升到最接近的共同祖先。
在這種情況下,“幾個組件需要反映相同的變化數據”的地方是您的<Total>
組件,因為正如您所說:
我的目標是根據子組件的信息在父組件中進行動態總計。
React 的核心模式之一是“數據向下流動” 。 換句話說,數據/狀態應該在您的應用程序中處於較高級別,並從那里“向下流動”到后代。 嘗試將數據保存在“子”組件( <Subtotal>
)中並且還更新其祖先中的 state 是 React 中的反模式,應該避免,因為這意味着您在兩個或多個位置跟蹤相同的 state一次。
嘗試這樣的事情:
function Total({ products }) {
// track "subtotals" in one place in state;
// the total value of all subtotals can be trivially derived from this
const [subtotals, setSubtotals] = React.useState(new Array(products.length).fill(0));
// our onChange handler will update the index of "subtotals"
// with the passed new value
const onChange = (newValue, i) => {
setSubtotals(oldSubtotals => {
const newSubtotals = [...oldSubtotals];
newSubtotals[i] = newValue;
return newSubtotals;
});
}
let total = 0;
for (let i = 0; i < subtotals.length; i++) {
total += subtotals[i] * products[i].price;
}
return (
<div>
{products.map((product, i) => (
<Subtotal product={product} value={subtotals[i]} onChange={onChange} index={i} />
))}
<span>Total: {total}</span>
</div>
);
}
// now <Subtotal> tracks no state, it is entirely stateless;
// it simply displays the correct information and calls its onChange as needed
function Subtotal({ product, value, onChange, index }) {
return (
<div>
<input
type="number"
// updated min to 0, unless you really want to force
// them to buy at least one...?
min={0}
onChange={(e) => onChange(e.target.value, index)}
value={value}
/>
<span>units * product price: {value * product.price}</span>
</div>
);
}
現在,總值的真實來源是<Total>
並且只有<Total>
。 state 沒有奇怪的分裂,其中一個組件試圖鏡像其他組件的 state。 <Total>
確切地知道每個小計正在跟蹤的值,並且只需將該值傳遞給子組件,以及 function 以更新 state。 但是您沒有在兩個地方跟蹤 state,這是非常非常糟糕的。
在Total
組件中為 state 使用數組怎么樣?
我盡量不改變你之前寫的代碼。
const initialState = [0, 0];
function Total({ products }) {
const [values, setValues] = useState(initialState);
// Below is for sum of array
const total = values.reduce((prev, val) => prev + val);
return (
<div>
{products.map((product, idx) => {
const handleChildToParent = (value) => {
setValues(values => {
const newValues = [...values];
newValues[idx] = value;
return newValues;
})
}
return (
<Subtotal product={product} childToParent={handleChildToParent} />
);
})}
<span>Total: {total}</span>
</div>
);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.