Bileşen yerine getDerivedStateFromProps yaşam döngüsü yöntemi nasıl kullanılır?


142

componentWillReceivePropsYeni bir yaşam döngüsü yöntemi lehine gelecek sürümlerde tamamen aşamalı olarak kaldırılacak gibi görünüyor getDerivedStateFromProps: static getDerivedStateFromProps () .

İnceleme sonucunda, artık this.propsve arasında nextPropsolduğu gibi doğrudan bir karşılaştırma yapamayacağınız anlaşılıyor componentWillReceiveProps. Bunun etrafında bir yol var mı?

Ayrıca, şimdi bir nesne döndürür. Dönüş değerinin temelde olduğunu varsaymak doğru this.setStatemudur?

Aşağıda çevrimiçi bulduğum bir örnek var: sahne / durumdan türetilen durum .

Önce

class ExampleComponent extends React.Component {
  state = {
    derivedData: computeDerivedState(this.props)
  };

  componentWillReceiveProps(nextProps) {
    if (this.props.someValue !== nextProps.someValue) {
      this.setState({
        derivedData: computeDerivedState(nextProps)
      });
    }
  }
}

Sonra

class ExampleComponent extends React.Component {
  // Initialize state in constructor,
  // Or with a property initializer.
  state = {};

  static getDerivedStateFromProps(nextProps, prevState) {
    if (prevState.someMirroredValue !== nextProps.someValue) {
      return {
        derivedData: computeDerivedState(nextProps),
        someMirroredValue: nextProps.someValue
      };
    }

    // Return null to indicate no change to state.
    return null;
  }
}

Yanıtlar:


96

Çıkarılması Hakkında componentWillReceiveProps: Eğer bir kombinasyonu ile kullanımlarını ele gerekir getDerivedStateFromPropsve componentDidUpdategörmek blog yazısı tepki örnek taşıma işlemlerinde. Ve evet, döndürülen nesne getDerivedStateFromPropsdurumu geçirilen bir nesneye benzer şekilde günceller setState.

Bir pervanenin eski değerine gerçekten ihtiyacınız varsa, bunu her zaman durumunuzda böyle bir şeyle önbelleğe alabilirsiniz:

state = {
  cachedSomeProp: null
  // ... rest of initial state
};

static getDerivedStateFromProps(nextProps, prevState) {
  // do things with nextProps.someProp and prevState.cachedSomeProp
  return {
    cachedSomeProp: nextProps.someProp,
    // ... other derived state properties
  };
}

Devleti etkilemeyen herhangi bir şey konabilir componentDidUpdateve hatta getSnapshotBeforeUpdateçok düşük seviyeli şeyler için bile vardır .

GÜNCELLEME: Yeni (ve eski) yaşam döngüsü yöntemleri hakkında fikir edinmek için, tepki-yaşam döngüsü-görselleştirici paketi yardımcı olabilir.


1
Ah, soruyu berbat ettim. Aslında demek istedimcomponentWillReceiveProps
Andrew

2
Önceki sahne tutmak için benim devlet kullanmayı düşündüm, ama gerçekten uygulamak için gereken ekstra kod ve mantık kaçınmak istedim. Ortaya koyduğun diğer şeyleri inceleyeceğim. Çok teşekkürler!
Andrew

4
Önceki bir durumu bir durumda depolamak zorunda kalmak, bu anlaşılması zor React API değişikliği için sadece ortak bir çözümdür. Birçok geliştiricinin gözleri için bu bir antipattern ve regresyon değişikliğine benziyor. Sizi Oblosys değil, Tepki ekibi.
AxeEffect

2
@AxeEffect Bunun nedeni getDerivedStateFromPropshiçbir zaman gerçekten hafızaya alınması için tasarlanmamıştır . Lütfen bunun yerine önerilen yaklaşımı açıkladığım yanıta bakın .
Dan Abramov

bu bir yazım hatası mı? Özledin ...mi Tüm durum nesnesini veya yalnızca önem verdiğimiz parçayı döndürmeliyiz.
programcı

51

Biz gibi son zamanlarda yayınlanan blog Tepki , vakaların büyük çoğunluğunda İhtiyacınız olmayan getDerivedStateFromPropshiç .

Sadece türetilmiş bazı verileri hesaplamak istiyorsanız:

  1. İçeride yap render
  2. Veya, yeniden hesaplamanın pahalı olması durumunda, gibi bir not yardımcısı kullanın memoize-one.

İşte en basit "after" örneği:

import memoize from "memoize-one";

class ExampleComponent extends React.Component {
  getDerivedData = memoize(computeDerivedState);

  render() {
    const derivedData = this.getDerivedData(this.props.someValue);
    // ...
  }
}

Daha fazla bilgi edinmek için blog yayınının bu bölümüne göz atın .


45
Vakaların büyük çoğunluğunda gerekli değilse , o zaman bu kadar çok ihtiyaç duyulan bir değişiklik olduğuna şaşırdım, bu da binlerce çalışma projesini kıracak. React ekibinin mühendisliğe başladığı anlaşılıyor.
Ska

39
BileşenWillReceiveProps ile getDerivedStateFromProps arasında geçiş yapın. Kırılma değil, mevcut tüm kodu yeniden düzenlemeye zorlar, bu da çok zaman alıcıdır. Ve vakaların büyük çoğunluğunda hiç kullanmamanız gerektiğini söylediğiniz için çok az faydası var gibi görünüyor. Neden ilk etapta kullanılmaması gereken bir şey için API değiştirme zahmetinden geçiyorsunuz.
Ska

4
Dan Abramov'un bu yorumu için bir cevap isterim.
Louis345

6
@DanAbramov bu değişikliğin neden ortaya çıktığı hakkında herhangi bir cevap?
Petros Kyriakou

3
Aslında projelerimizde bu çok kullanılıyor. Snackbar'lar gibi şeyleri yeni verilerin geldiği zamanlarda ekranlarda göstermek için, 1 örnek. componentWillReceivePropsbasitti ve işe yaradı. Neden bu statik çöp için kaldır ...
Oliver Dixon

6

Dan Abramov tarafından belirtildiği gibi

Renderın içinde yap

Aslında bu yaklaşımı memoise one ile durum hesaplamalarına her türlü vekil sahne için kullanıyoruz.

Kodumuz bu şekilde görünüyor

// ./decorators/memoized.js  
import memoizeOne from 'memoize-one';

export function memoized(target, key, descriptor) {
  descriptor.value = memoizeOne(descriptor.value);
  return descriptor;
}

// ./components/exampleComponent.js
import React from 'react';
import { memoized } from 'src/decorators';

class ExampleComponent extends React.Component {
  buildValuesFromProps() {
    const {
      watchedProp1,
      watchedProp2,
      watchedProp3,
      watchedProp4,
      watchedProp5,
    } = this.props
    return {
      value1: buildValue1(watchedProp1, watchedProp2),
      value2: buildValue2(watchedProp1, watchedProp3, watchedProp5),
      value3: buildValue3(watchedProp3, watchedProp4, watchedProp5),
    }
  }

  @memoized
  buildValue1(watchedProp1, watchedProp2) {
    return ...;
  }

  @memoized
  buildValue2(watchedProp1, watchedProp3, watchedProp5) {
    return ...;
  }

  @memoized
  buildValue3(watchedProp3, watchedProp4, watchedProp5) {
    return ...;
  }

  render() {
    const {
      value1,
      value2,
      value3
    } = this.buildValuesFromProps();

    return (
      <div>
        <Component1 value={value1}>
        <Component2 value={value2}>
        <Component3 value={value3}>
      </div>
    );
  }
}

Bunun avantajları, tonlarca karşılaştırma plakasını kodlamanıza gerek kalmaması getDerivedStateFromPropsveya componentWillReceivePropsbir kurucu içinde kopyala yapıştır başlatmasını atlayabilmenizdir.

NOT:

Bu yaklaşım yalnızca destek malzemelerini durum için proxy yapmak için kullanılır, bazı iç durum mantığınız olması durumunda hala bileşen yaşam döngülerinde ele alınması gerekir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.