Reactjs 功能组件随useMoom/React.memo一起消失

Reactjs 功能组件随useMoom/React.memo一起消失,reactjs,react-native,Reactjs,React Native,我正试着集中精力使用usemo(或React.memo)来优化一些组件渲染 我有个无法解释的问题 我有以下代码: [...] const [ cards, setCards ] = useState<Card[]>([]) function addCard(){ setCards([...cards, {name: 'card-' + cards.length, counter: 0, type: 'memo'}]) } func

我正试着集中精力使用
usemo
(或
React.memo
)来优化一些组件渲染

我有个无法解释的问题

我有以下代码:

[...]
    const [ cards, setCards ] = useState<Card[]>([])


    function addCard(){
        setCards([...cards, {name: 'card-' + cards.length, counter: 0, type: 'memo'}])
    }

    function onPressCard(index: number){
        cards[index].counter += 1
        setCards([...cards])
    }

   return (
     [...]
    {
      cards.map((x, index) => 
        <Card key={index} {...x} onPress={() => onPressCard(index)}/>
    }
    [...]
)

[…]
const[cards,setCards]=useState([])
函数addCard(){
setCards([…cards,{name:'card-'+cards.length,计数器:0,键入:'memo'}])
}
印刷卡上的功能(索引:编号){
卡片[索引]。计数器+=1
设置卡片([…卡片])
}
返回(
[...]
{
卡片.地图((x,索引)=>
onPressCard(索引)}/>
}
[...]
)
定义为


const Card: FC<CardProps> = function({ name, counter, onPress }){
    const counterRef = useRef(0)

    const item = useMemo(() => {
        counterRef.current +=1

        return (
        <RectButton onPress={onPress} style={[styles.card, { backgroundColor: 'lightcoral' }]}>
            <Text style={styles.text}>{ name }</Text>
            <Text style={styles.counter}> { `counter ${counter}` }</Text>
            <Text style={styles.counter}>{ `render: ${counterRef.current}`}</Text>
        </RectButton>
        )
    }, [name, counter])

    return item
}
const areEqual = function(prevProps: Card, nextProps: Card){
    return (
        (prevProps.name === nextProps.name) &&
        (prevProps.counter === nextProps.counter)
    )
}

const Card = React.memo<CardProps>(({ name, counter, onPress }) => {
    const counterRef = useRef(0)

    counterRef.current +=1

    return (
        <RectButton onPress={onPress} style={[styles.card, { backgroundColor: 'lightcoral' }]}>
            <Text style={styles.text}>{ name }</Text>
            <Text style={styles.counter}> { `counter ${counter}` }</Text>
            <Text style={styles.counter}>{ `render: ${counterRef.current}`}</Text>
        </RectButton>
        )
}, areEqual)

常量卡:FC=函数({name,counter,onPress}){
const counterRef=useRef(0)
const item=useMoom(()=>{
反向参考电流+=1
返回(
{name}
{`counter${counter}`}
{`render:${counterRef.current}`}
)
},[姓名,柜台])
退货项目
}
为什么,当我按下列表中的一个项目(最后一个除外)时,以下所有项目都消失了?

编辑:同样的情况发生在定义为


const Card: FC<CardProps> = function({ name, counter, onPress }){
    const counterRef = useRef(0)

    const item = useMemo(() => {
        counterRef.current +=1

        return (
        <RectButton onPress={onPress} style={[styles.card, { backgroundColor: 'lightcoral' }]}>
            <Text style={styles.text}>{ name }</Text>
            <Text style={styles.counter}> { `counter ${counter}` }</Text>
            <Text style={styles.counter}>{ `render: ${counterRef.current}`}</Text>
        </RectButton>
        )
    }, [name, counter])

    return item
}
const areEqual = function(prevProps: Card, nextProps: Card){
    return (
        (prevProps.name === nextProps.name) &&
        (prevProps.counter === nextProps.counter)
    )
}

const Card = React.memo<CardProps>(({ name, counter, onPress }) => {
    const counterRef = useRef(0)

    counterRef.current +=1

    return (
        <RectButton onPress={onPress} style={[styles.card, { backgroundColor: 'lightcoral' }]}>
            <Text style={styles.text}>{ name }</Text>
            <Text style={styles.counter}> { `counter ${counter}` }</Text>
            <Text style={styles.counter}>{ `render: ${counterRef.current}`}</Text>
        </RectButton>
        )
}, areEqual)
const areEqual=函数(前一个道具:卡,下一个道具:卡){
返回(
(prevProps.name==nextProps.name)&&
(prevProps.counter===nextProps.counter)
)
}
const Card=React.memo({name,counter,onPress})=>{
const counterRef=useRef(0)
反向参考电流+=1
返回(
{name}
{`counter${counter}`}
{`render:${counterRef.current}`}
)
},他们是平等的)

问题在于,已记忆的组件包含对旧版本的
onPress
的引用。旧版本的
onPress
在其关闭中有一个旧版本的
cards
。点击按钮将调用旧函数,该函数根据旧状态更新父级状态,并且旧状态中的项目较少。

修复此问题的一个选项是使用setCards的函数版本,以便根据最新状态进行更新。此外,我更新了代码,不再对旧卡进行变异:

function onPressCard(index: number){
  setCards(oldCards => {
    const newCards = [...oldCards];
    newCards[index] = {...oldCards[index]};
    newCards[index].counter += 1;
    return newCards;
  })
}
另一个选项是将onPress添加到UseMoom的条件中,但由于onPress函数一直在更改,因此您最终无法从记忆中获得任何东西。如果onPress本身使用useCallback进行了记忆,则可以改进这一点:

const onPressCard = useCallback((index: number) => {
  cards[index].counter += 1;
  setCards([...cards]);
}, [cards])

// ...

const item = useMemo(() => {
  counterRef.current +=1

  return ( /* jsx omitted for brevity */ )
}, [name, counter, onPress])    

onPressCard的作用是什么?我不确定useMemo是否被设计用于记忆整个组件。它与React.memo完全不同。@NicholasTower我更新了我的question@nubinub当我使用React.memo时,也会发生同样的情况,使用相同的comparisonPerfect,你能用
useCallback
演示一个例子吗ne@Orelus我在.UseCallback中添加了这一点,它与useMemo非常相似。它只是假设您想要记忆一个函数。
UseCallback(()=>“hello world”)
useMemo(()=>()=>()=>“hello world”)相同。