繁体   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