วิธีใช้วิธีวงจรชีวิต getDerivedStateFromProps ซึ่งตรงข้ามกับ componentWillReceiveProps


142

ดูเหมือนว่าcomponentWillReceivePropsเป็นไปได้ที่จะค่อย ๆ ออกมาในรุ่นมาในความโปรดปรานของวิธีการที่วงจรชีวิตใหม่getDerivedStateFromProps: getDerivedStateFromProps คงที่ ()

เมื่อตรวจสอบก็ดูเหมือนว่าคุณอยู่ในขณะนี้ไม่สามารถที่จะทำให้การเปรียบเทียบโดยตรงระหว่างthis.propsและเช่นเดียวกับที่คุณสามารถในnextProps componentWillReceivePropsมีวิธีแก้ไขไหม?

นอกจากนี้มันจะส่งคืนวัตถุ ฉันถูกต้องหรือไม่ที่จะสมมติว่าค่าส่งคืนเป็นหลักthis.setStateหรือไม่

ด้านล่างเป็นตัวอย่างที่ผมพบออนไลน์: รัฐที่ได้มาจากการประกอบฉาก / รัฐ

ก่อน

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

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

หลังจาก

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;
  }
}

คำตอบ:


96

เกี่ยวกับการลบcomponentWillReceiveProps: คุณควรจะสามารถจัดการกับการใช้งานด้วยการรวมกันของgetDerivedStateFromPropsและcomponentDidUpdateดูโพสต์บล็อกตอบโต้การโยกย้าย และใช่วัตถุที่ส่งกลับโดยการปรับปรุงรัฐในทำนองเดียวกันกับวัตถุที่ส่งผ่านไปยังgetDerivedStateFromPropssetState

ในกรณีที่คุณต้องการคุณค่าเก่าแก่ของเสาจริง ๆ คุณสามารถเก็บไว้ในสถานะของคุณด้วยสิ่งนี้:

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
  };
}

สิ่งใดก็ตามที่ไม่ส่งผลกระทบต่อรัฐสามารถใส่เข้าไปcomponentDidUpdateได้และยังมีgetSnapshotBeforeUpdateสิ่งที่อยู่ในระดับต่ำมาก

อัปเดต: เพื่อรับความรู้สึกเกี่ยวกับวิธีวงจรชีวิตใหม่ (และเก่า) แพคเกจreact-lifecycle-visualizerอาจมีประโยชน์


1
ฮึฉันทำให้คำถามสับสน จริง ๆ แล้วฉันหมายถึงcomponentWillReceiveProps
แอนดรู

2
ฉันเคยคิดว่าจะใช้สถานะของฉันเพื่อเก็บอุปกรณ์ประกอบฉากก่อนหน้านี้ แต่ฉันต้องการหลีกเลี่ยงรหัสพิเศษและตรรกะที่ใช้ในการปรับใช้ ฉันจะดูสิ่งอื่น ๆ ที่คุณนำมาใช้ ขอบคุณมาก!
แอนดรู

4
การจัดเก็บ prop ก่อนหน้านี้ในสถานะเป็นเพียงวิธีแก้ปัญหาสำเร็จรูปสำหรับการเปลี่ยนแปลง React API ที่เข้าใจยาก สำหรับสายตาของนักพัฒนาจำนวนมากสิ่งนี้ดูเหมือนเป็นปฏิปักษ์และการเปลี่ยนแปลงการถดถอย ไม่วิจารณ์คุณว่า Oblosys แต่เป็นทีม React
AxeEffect

2
@AxeEffect นี่เป็นเพราะgetDerivedStateFromPropsไม่เคยมีจุดประสงค์ในการบันทึกความจำจริงๆ โปรดดูคำตอบของฉันด้านล่างที่ฉันอธิบายวิธีการที่แนะนำแทน
Dan Abramov

นั่นคือการพิมพ์ผิด? คุณพลาด...หรือไม่ นั่นคือเราควรคืนค่าสถานะทั้งหมดหรือเฉพาะส่วนที่เราสนใจ
theprogrammer

51

ในฐานะที่เราเพิ่งโพสต์ในบล็อก React ,ในส่วนใหญ่ของกรณีที่คุณไม่จำเป็นgetDerivedStateFromPropsที่ทุกคน

หากคุณต้องการคำนวณข้อมูลที่ได้มาบางส่วน:

  1. ทำมันภายใน render
  2. หรือหากคำนวณอีกครั้งว่ามันแพงใช้ผู้ช่วย memoization memoize-oneเช่น

นี่คือตัวอย่าง "after" ที่ง่ายที่สุด:

import memoize from "memoize-one";

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

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

ลองอ่านหัวข้อนี้ของบล็อกโพสต์เพื่อเรียนรู้เพิ่มเติม


45
ถ้ามันไม่จำเป็นต้องอยู่ในที่กว้างใหญ่กรณีส่วนใหญ่แล้วผมประหลาดใจนี้คือการเปลี่ยนแปลงที่จำเป็นไม่ดีดังกล่าวหนึ่งที่จะทำลายหลายพันโครงการทำงาน ดูเหมือนว่าทีม React จะเริ่มต้นทำงานด้านวิศวกรรม
Ska

39
เปลี่ยนจาก componentWillReceiveProps เป็น getDerivedStateFromProps มันไม่ได้ทำลาย แต่บังคับให้ refactor รหัสที่มีอยู่ทั้งหมดซึ่งใช้เวลานานมาก และดูเหมือนว่าจะได้ประโยชน์น้อยมากเนื่องจากคุณบอกว่าคุณไม่ควรใช้มันในทุกกรณี ทำไมต้องผ่านความยุ่งยากในการเปลี่ยน API สำหรับบางสิ่งที่ไม่ควรใช้ตั้งแต่แรก
Ska

4
ฉันจะรักการตอบสนองต่อความคิดเห็นนี้จาก Dan Abramov
Louis345

6
@DanAbramov คำตอบใด ๆ เกี่ยวกับสาเหตุที่การเปลี่ยนแปลงนี้มาเป็นอย่างไร
Petros Kyriakou

3
จริง ๆ แล้วในโครงการของเรานี่ใช้บ่อยมาก สำหรับการแสดงสิ่งต่าง ๆ เช่น Snackbars บนหน้าจอเมื่อมีข้อมูลใหม่เข้ามาตัวอย่างหนึ่ง componentWillReceivePropsง่ายและใช้งานได้ เหตุใดจึงต้องลบทิ้งสำหรับถังขยะแบบคงที่นี้ ...
Oliver Dixon

6

ดังที่ Dan Abramov พูดถึง

ทำมันให้ถูกต้องภายใน

เราใช้วิธีการนั้นกับอุปกรณ์ช่วยจำสำหรับอุปกรณ์ประกอบการมอบฉันทะประเภทใดก็ได้เพื่อการคำนวณ

รหัสของเรามีลักษณะเช่นนี้

// ./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>
    );
  }
}

ประโยชน์ของมันคือคุณไม่จำเป็นต้องเขียนโค้ดจำนวนมากของการเปรียบเทียบสำเร็จรูปในและgetDerivedStateFromPropsหรือcomponentWillReceivePropsคุณสามารถข้ามการเริ่มต้นการคัดลอกวางในตัวสร้าง

บันทึก:

วิธีนี้ใช้สำหรับการพร็อกซี่อุปกรณ์ประกอบฉากที่จะระบุในกรณีที่คุณมีตรรกะภายในบางอย่างก็ยังต้องได้รับการจัดการในวงจรชีวิตของส่วนประกอบ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.