[英]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.