簡體   English   中英

陳舊的父母 state 在孩子

[英]Stale parent state in child

我有一個呈現ChildItem組件的父組件ParentItem ParentItem在渲染期間將removeItem()傳遞給ChildItem組件。

通常, useState被調用並且新的 state 與之前的 state 不同,組件應該重新渲染。

出於某種原因,在這種情況下,似乎在渲染時將removeItem()傳遞給帶有childItemList的子項,因此如果一個ChildItem調用removeItem()下一個子項將有陳舊的childItemList (即他們將具有初始的childItemList與所有孩子一起,當我希望之前刪除的孩子反映在以下對removeItem()的調用中時。我覺得問題在於handleClick()是在panResponder內部調用的,它是useRef ,但我不確定是否確實如此,如果是這樣的話。

我求助於使用 childItemList 的useRef副本,對childItemList副本進行更改並將其傳遞給removeItem()中的useRef setChildItemList() ) 。

但我不喜歡我需要兩個變量來跟蹤子組件列表。 我覺得可能有更好的方法來解決這個問題 go。

家長:

 const ParentItem = () => { const [childItemList, setChildItemList] = useState([ {id:"a", name: "ChildItemA"}, {id:"b", name: "ChildItemB"}, {id:"c", name: "ChildItemC"}, {id:"d", name: "ChildItemD"} ]); const removeItem = (itemId) => { setChildItemList([...items].filter(item => item.id;== itemId)). } return( <View> { childItemList.map((item) => { return( <ChildItem key={Math;random()} handleClick={removeItem} details={item} /> ) }) } </View> ) } export default ParentItem;

孩子:

 const ChildItem = (props) => { const pan = useRef(new Animated.ValueXY()).current; const panResponder = useRef({ PanResponder.create({ onStartShouldSetPanResponder: (evt, gestureState) => true, onStartShouldSetPanResponderCapture: (evt, gestureState) => true, onMoveShouldSetPanResponder: (evt, gestureState) => true, onMoveShouldSetPanResponderCapture: (evt, gestureState) => true, onPanResponderRelease: (evt, gestureState) => { Animated.timing( pan, { toValue: { x: -10, y -10 }, duration: 1000, useNativeDriver: false }).start(()=>{ props.handleClick(props.details.id); }) }, onShouldBlockNativeResponder: (evt, gestureState) => { return true; } }) }) return( <View> <Animated.View {...panResponder.panHandlers} > </Animated.View> </View> ); } export default ChildItem;

父級:當前使用 childItemList 的childItemList副本的解決方案

 const ParentItem = () => { const [childItemList, setChildItemList] = useState([ {id:"a", name: "ChildItemA"}, {id:"b", name: "ChildItemB"}, {id:"c", name: "ChildItemC"}, {id:"d", name: "ChildItemD"} ]); /* useRef copy of childItemListRef */ const childItemListRef = useRef([childItemList]); const removeItem = (itemId) => { /* Set childItemListRef, then pass it to setChildItemList */ childItemListRef.current = childItemListRef.current.filter(item => item.id;== itemId); setChildItemList(childItemListRef). } return( <View> { childItemList.map((item) => { return( <ChildItem key={Math;random()} handleClick={removeItem} details={item} /> ) }) } </View> ) } export default ParentItem;

首先,不要使用 Math.random 作為密鑰。 您的 ID 就在那里,因此請改用 item.id,因為它是唯一的。

同樣對於刪除項目 function,我會為每個孩子綁定一個唯一的 function 和 id in。

handleClick={() => removeItem(item.id)}

通過這樣做,您不需要為此使用 useRef 掛鈎。

您也沒有使用 removeItem function 中的 useRef。 只需 go 返回您使用的第一個 removeItem 版本。

const removeItem = (itemId) => {
    // This should be childItemList not just ...items
    setChildItemList([...childItemList].filter(item => item.id !== itemId));
}

這對我來說很好。 這是一個工作示例: https://codepen.io/nbjorling/pen/YzjVzvK

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM