javascript - React, dizideki her çocuğun benzersiz bir anahtara sahip olmasına rağmen listemi yeniden render ediyor


Yani, anladığım kadarıyla React sadece yeni anahtarlara sahip yeni öğeleri yeniden render ediyor. Ama bu benim için çalışmıyor. Üç ile sınırlı bir gönderi listem var. Kullanıcı sayfanın altına kaydırdığında, sınıra 3 ekliyorum, bu da sayfanın altında 3 eski gönderinin gösterilmesi gerektiği anlamına geliyor. Şu anda çalışan bir şeyim var, ancak tüm liste yeniden render ediliyor. Ve bu ayrıca istenmeyen bir şekilde en üste atlıyor (bunu düzeltebilirim, asıl sorun yeniden render edilme). Hepsinin benzersiz anahtarları var. Bu davranışı nasıl engelleyebilirim?

thisGetsCalledWhenANewPostComesIn(newPost){
    let newPosts = _.clone(this.state.posts);
    newPosts.push(newPost);
    newPosts.sort((a,b) => b.time_posted - a.time_posted); 
    this.setState({posts: newPosts});
}

render(){
     return (
         <div ref={ref => {this.timelineRef = ref;}} style={styles.container}>
             {this.state.posts.map(post =>
                 <Post key={post.id} post={post} />
             )}
         </div>
     );
}

Cevap #1

Sadece benzersiz anahtarlara sahip olmak, değişmeyen bileşenlerin yeniden render edilmesini engellemez. Bileşenler için PureComponent'i genişletmez veya shouldComponentUpdate'i uygulamazsanız, React bileşeni render() etmek ve son sonuçla karşılaştırmak zorunda kalacaktır.

Peki gerçekten shouldComponentUpdate ile ilgiliyken neden anahtarlara ihtiyacımız var?

Bir listedeki her bileşene benzersiz bir anahtar vermenin amacı, öznitelikleri doğru bileşen örneklerine iletmektir, böylece yeni ve eski öznitelikleri doğru bir şekilde karşılaştırabilirler.

Bir öğe listemiz olduğunu hayal edin, örneğin:

  • A -> bileşenÖrneğiA
  • B -> bileşenÖrneğiB
  • C -> bileşenÖrneğiC

Bir filtre uygulandıktan sonra, bileşenlerin yeni listesini göstermek için liste yeniden render edilmelidir, örneğin:

  • C -> ?

Doğru benzersiz anahtarlar olmadan, daha önce A'yı render eden bileşen artık C için prop(lar) alacaktır. C değişmemiş olsa bile, bileşen tamamen farklı veriler aldığı için yeniden render etmek zorunda kalacaktır:

  • C -> componentInstanceA/TAAAAMAM HAA!

Uygun benzersiz anahtarlarla, C bileşenini render eden bileşen tekrar C'yi alacaktır. Daha sonra shouldComponentUpdate, render() çıktısının aynı olacağını fark edebilecek ve bileşenin yeniden render edilmesine gerek kalmayacaktır:

  • C -> bileşenÖrneğiC

Eğer öğelerinizin listesi render edilmesi uzun sürüyorsa, örneğin liste uzunsa veya her bir öğe karmaşık bir veri seti içeriyorsa, gereksiz yeniden render edilmesini önlemekten fayda sağlayacaksınız.

Kişisel anekdot

Her biri binlerce DOM öğesi üreten yüzlerce öğeden oluşan bir listeye sahip bir projede, değişiklik yapmak

list.map((item, index) => <SomeComp key={index} ... />)

için

list.map(item => <SomeComp key={item.id} ... />)

Render süresini birkaç saniye azalttı. Anahtar olarak asla dizi indeksini kullanmayın.

Cevap #2

Post bileşeninde shouldComponentUpdate(nextProps, nextState) metodunu uygulamanız gerekecek. Varsayılan React Component yerine Post bileşenini PureComponent sınıfını genişleterek düşünün.

İyi şanslar!

Not: render metodunuzda div için bir ref parametresi olarak bir string kullanabilirsiniz, şöyle ki:

render() {
  return (
    <div 
      ref='myRef'
      style={styles.container}
    >
      {this.getPostViews()}
    </div>
  );
}

O zaman, bu elemana başvurmak istiyorsanız, bunu this.refs.myRef gibi kullanın. Her neyse, bu sadece kişisel bir tercihtir.