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