ให้เรตสมาชิก: 3 / 5

ดาวใช้งานดาวใช้งานดาวใช้งานดาวไม่ได้ใช้งานดาวไม่ได้ใช้งาน
 

Lifting State Up

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

     เราจะเริ่มต้นด้วย Elements ที่ชื่อว่า BoilingVerdict และแสดงค่าอุณหภูมิ เมื่อน้ำเดือด :

function BoilingVerdict(props) {
  if (props.celsius >= 100) {
    return <p>The water would boil.</p>;
  }
  return <p>The water would not boil.</p>;
}

     จากนั้นเราจะสร้าง Component ที่เรียกว่าเครื่องคิดเลข มันทำให้ <input> ที่ช่วยให้เราสามารถป้อนอุณหภูมิและเก็บค่าใน this.state.temperature

     นอกจากนี้ จะแสดงค่า BoilingVerdict สำหรับค่า Input ในปัจจุบัน ข้างล่างนี้จะเป็นโค้ดอุณหภูมิน้ำ :

class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {temperature: ''};
  }

  handleChange(e) {
    this.setState({temperature: e.target.value});
  }

  render() {
    const temperature = this.state.temperature;
    return (
      <fieldset>
        <legend>Enter temperature in Celsius:</legend>
        <input
          value={temperature}
          onChange={this.handleChange} />
        <BoilingVerdict
          celsius={parseFloat(temperature)} />
      </fieldset>
    );
  }
}

     ผลที่ได้มีดังนี้ : ถ้าเรากรอกอุณหภูมิ 10 ลงไป ก็จะแสดงค่าว่า not boil แต่ถ้าเรากรอก 100 ลงไป จะแสดงค่า boil

temptemp

 

การเพิ่ม Input ที่สอง

     ต่อไปเราจะให้ข้อกำหนดใหม่นอกเหนือจากการป้อนค่า Celsius เราจะมี Input ของ Fahrenheit และจะถูกเก็บไว้ในข้อมูลตรงกัน เราจะเริ่มจากการดึง Component TemperatureInput จาก Calculator โดยเราจะเพิ่มสเกลใหม่ลงไป อาจจะเป็น "C" หรือ "F" :

const scaleNames = {
  c: 'Celsius',
  f: 'Fahrenheit'
};

class TemperatureInput extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {temperature: ''};
  }

  handleChange(e) {
    this.setState({temperature: e.target.value});
  }

  render() {
    const temperature = this.state.temperature;
    const scale = this.props.scale;
    return (
      <fieldset>
        <legend>Enter temperature in {scaleNames[scale]}:</legend>
        <input value={temperature}
               onChange={this.handleChange} />
      </fieldset>
    );
  }
}

     ตอนนี้เราสามารถเปลี่ยน Calculator เพื่อแสดงอุณหภูมิสองแบบแยกกันได้ :

class Calculator extends React.Component {
  render() {
    return (
      <div>
        <TemperatureInput scale="c" />
        <TemperatureInput scale="f" />
      </div>
    );
  }
}

     ผลลัพธ์ที่ได้ : จะได้ Input สองช่อง

temp2temp2

     ตอนนี้เรามี Input สองตัว แต่เมื่อเราป้อนอุณหภูมิในรายการใดรายการหนึ่งข้อมูลอื่น ๆ จะไม่อัปเดต สิ่งนี้ขัดแย้งกับข้อกำหนด : ดังนั้นเราต้องทำให้ข้อมูลตรงกัน

     เรายังไม่สามารถแสดง BoilingVerdict จาก Calculator ได้ เพราะว่า Calculator ไม่ทราบอุณหภูมิปัจจุบัน เพราะมันถูกซ่อนอยู่ภายใน TemperatureInput

 

การเขียนฟังก์ชั่นการแปลงค่า

     ขั้นแรกเราจะเขียนสองฟังก์ชั่นเพื่อแปลงจาก Celsius เป็น Fahrenheit และมีการแสดงค่ากลับกัน :

function toCelsius(fahrenheit) {
  return (fahrenheit - 32) * 5 / 9;
}

function toFahrenheit(celsius) {
  return (celsius * 9 / 5) + 32;
}

     ฟังก์ชันทั้งสอง แปลงตัวเลข เราจะเขียนฟังก์ชันอื่นที่ใช้สตริง temperature และฟังก์ชันแปลงเป็น Arguments และส่งกลับสตริง เราจะใช้มันในการคำนวณค่าของหนึ่ง Input โดยใช้ Input อื่น ๆ ส่งกลับสตริงที่ว่างเปล่าใน temperature ที่ไม่ถูกต้องและจะให้ผลลัพธ์ปัดเศษทศนิยมที่สาม :

function tryConvert(temperature, convert) {
  const input = parseFloat(temperature);
  if (Number.isNaN(input)) {
    return '';
  }
  const output = convert(input);
  const rounded = Math.round(output * 1000) / 1000;
  return rounded.toString();
}

     ตัวอย่างเช่น tryConvert ('abc', toCelsius) จะ return ค่าว่างและ tryConvert ('10 .22 ', toF) จะแสดงผลลัพธ์ '50 .396'

 

Lifting State Up

     ตอนนี้ทั้งสอง Component TemperatureInput อิสระเก็บค่าในสถานะ Local :

class TemperatureInput extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
    this.state = {temperature: ''};
  }

  handleChange(e) {
    this.setState({temperature: e.target.value});
  }

  render() {
    const temperature = this.state.temperature;
    // ...  

     อย่างไรก็ตามเราต้องการให้ Input ทั้งสองตัวนี้ซิงค์กัน เมื่อเราอัพเดต Input Celsius ค่าของ Fahrenheit ควรสะท้อนถึงอุณหภูมิที่เปลี่ยนแปลงและในทางกลับกัน

     ใน React การแบ่งปัน state ทำได้โดยการเคลื่อนย้ายไปยัง parent ร่วมกันที่ใกล้เคียงที่สุดของ Component ที่จำเป็นต้องใช้ นี้เรียกว่า "Lifting State Up" เราจะลบสถานะภายในออกจาก TemperatureInput และย้ายไปยัง Calculator แทน

     สำหรับอุณหภูมิปัจจุบันใน Input ทั้งสอง สามารถสั่งให้ทั้งสองมีค่าที่สอดคล้องกัน เนื่องจากส่วนกำหนดค่าของส่วนประกอบ TemperatureInput ทั้งสองมาจาก Component Calculator หลักเดียวกัน Input ทั้งสองจะซิงค์กันอยู่เสมอ

 

มาดูกันใน Step ต่อไปเลยดีกว่า

     ขั้นแรกเราจะแทนที่ this.state.temperature ด้วย this.props.temperature ใน Component TemperatureInput ตอนนี้สมมติว่า this.props.temperature มีอยู่แล้วแม้ว่าเราจะต้องส่งต่อจาก Calculator ในอนาคต :

render() {
    // Before: const temperature = this.state.temperature;
    const temperature = this.props.temperature;
    // ...

     เรารู้ว่า props เป็นแบบอ่านอย่างเดียว เมื่อ Temperature อยู่ใน Local state TemperatureInput สามารถเรียกใช้ this.setState() เพื่อเปลี่ยนได้ อย่างไรก็ตามตอนนี้ Temperature ที่มาจาก parent เป็น props TemperatureInput ที่ไม่มีการควบคุม

     ใน React จะแก้ไขได้โดยการทำให้ Component เป็นตัวควบคุม เช่นเดียวกับ DOM <input> ยอมรับทั้ง value และ onChange prop ดังนั้น TemperatureInput ที่กำหนดเองจึงสามารถรับ Temperature ทั้งสอง onTemperatureChange จาก Calculator หลักได้

     ตอนนี้เมื่อ TemperatureInput ต้องการที่จะปรับปรุงอุณหภูมิ จะมีการเรียก this.props.onTemperatureChange :

  handleChange(e) {
    // Before: this.setState({temperature: e.target.value});
    this.props.onTemperatureChange(e.target.value);
    // ...

     Example โค้ดคำนวนอุณหภูมิที่สมบูรณ์แล้ว :

class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.handleCelsiusChange = this.handleCelsiusChange.bind(this);
    this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this);
    this.state = {temperature: '', scale: 'c'};
  }

  handleCelsiusChange(temperature) {
    this.setState({scale: 'c', temperature});
  }

  handleFahrenheitChange(temperature) {
    this.setState({scale: 'f', temperature});
  }

  render() {
    const scale = this.state.scale;
    const temperature = this.state.temperature;
    const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
    const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;

    return (
      <div>
        <TemperatureInput
          scale="c"
          temperature={celsius}
          onTemperatureChange={this.handleCelsiusChange} />
        <TemperatureInput
          scale="f"
          temperature={fahrenheit}
          onTemperatureChange={this.handleFahrenheitChange} />
        <BoilingVerdict
          celsius={parseFloat(celsius)} />
      </div>
    );
  }
}

     ผลลัพธ์ที่ได้ : เมื่อกรอกอุณหภูมิลงไปในช่อง Celsius จะมีการคำนวนค่า Fahrenheit และแสดงออกมาในช่อง Output

 

temp3temp3

 

 

 

ข้อมูลอ้างอิง : https://reactjs.org

กระทู้ล่าสุดจากเว็บบอร์ด
หัวข้อกระทู้
ตอบ
เปิดดู
ล่าสุด
คู่มือวิธีการลบแบบเก็บไว้ในถังขยะใน phpbb โดยแอดมินเท่านั้นที่สามารถเห็นในส่วนนี้ User อื่นไม่สามารถทำได้
โดย จันนุสรณ์ ดีแก่ อ 19 ก.พ. 2019 9:15 am บอร์ด phpBB user Guide Knowledge
0
1
อ 19 ก.พ. 2019 9:15 am โดย จันนุสรณ์ ดีแก่
R - mdsoft_partner_fields Module ปรับเพิ่มฟิลด์ lead > partner
โดย thatsawan จ 18 ก.พ. 2019 11:18 pm บอร์ด MlineCRM Line + MD-CRM
1
3
อ 19 ก.พ. 2019 6:51 am โดย mindphp
อยากทราบวิธีการดูดข้อมูลจากเว็บอื่น
โดย newbie จ 18 ก.พ. 2019 3:05 pm บอร์ด Programming - PHP
0
9
จ 18 ก.พ. 2019 3:05 pm โดย newbie
Q - ตัว search tools ใน Joomla 4 ลอง search แล้วไม่สามารถเคลียได้
โดย Parichat ส 16 ก.พ. 2019 6:57 pm บอร์ด Joomla Dev
0
3
ส 16 ก.พ. 2019 6:57 pm โดย Parichat
อยากทราบวิธีการ ปิด ไม่ใช้ เทมเพลตกลายเป็น เว็บ responsive ใน phpbb
โดย Ittichai_chupol ส 16 ก.พ. 2019 6:56 pm บอร์ด Programming - PHP
0
14
ส 16 ก.พ. 2019 6:56 pm โดย Ittichai_chupol
อยากทราบวิธีการแก้ไข้ ปัญหา ขณะเปิดใช้งาน Extension ใน phpbb
โดย Ittichai_chupol ส 16 ก.พ. 2019 6:22 pm บอร์ด Programming - PHP
0
13
ส 16 ก.พ. 2019 6:22 pm โดย Ittichai_chupol
อยากทราบวิธีการตรวจสอบสิทธิ์ ของผู้ใช้งาน
โดย Ittichai_chupol ส 16 ก.พ. 2019 1:26 pm บอร์ด Programming - PHP
0
19
ส 16 ก.พ. 2019 1:26 pm โดย Ittichai_chupol
วิธีแก้ปัญหาบันทึกข้อมูลไม่ลงใน Joomla Version 4
โดย Parichat ส 16 ก.พ. 2019 11:49 am บอร์ด Joomla Dev
0
2
ส 16 ก.พ. 2019 11:49 am โดย Parichat
ทำความรู้จักกับ วิธีจัดการการแจ้งเตือน พร้อมวิธีการบันทึกการแจ้งเตือนว่าอ่านแล้ว ในหลายๆหัวข้อพร้อมกัน
โดย จันนุสรณ์ ดีแก่ ส 16 ก.พ. 2019 10:26 am บอร์ด phpBB user Guide Knowledge
0
23
ส 16 ก.พ. 2019 10:26 am โดย จันนุสรณ์ ดีแก่
งานประจำวันที่ 16 กุมภาพันธ์ 2562
โดย Four ส 16 ก.พ. 2019 9:47 am บอร์ด M077 - อิษยา งามสอาด
1
10
ส 16 ก.พ. 2019 7:13 pm โดย Four
Mod MDFiles Popular 모듈 소개 MDFile에서 파일을 가져와 표시
โดย wipaporn ศ 15 ก.พ. 2019 6:06 pm บอร์ด korean Language - 한국어
0
18
ศ 15 ก.พ. 2019 6:06 pm โดย wipaporn
MDFiles Featured modules를 소개하면 MDFile에서 파일을 가져와 보여준다.
โดย wipaporn ศ 15 ก.พ. 2019 6:06 pm บอร์ด korean Language - 한국어
0
18
ศ 15 ก.พ. 2019 6:06 pm โดย wipaporn
Q - เกิดerror โค้ด ขึ้นว่า AttributeError: 'TextTestResult' object has no attribute 'openwed_Login'
โดย ธวัชชัย แสนหาญ ศ 15 ก.พ. 2019 5:55 pm บอร์ด Programming - C/C++ & java & Python
0
26
ศ 15 ก.พ. 2019 5:55 pm โดย ธวัชชัย แสนหาญ
마스터 사이트에서 Web Client로 문서를 끌어오기 위한 플러그인인 Editors XTD Multicontent를 소개한다.
โดย wipaporn ศ 15 ก.พ. 2019 5:48 pm บอร์ด korean Language - 한국어
0
6
ศ 15 ก.พ. 2019 5:48 pm โดย wipaporn
Joomla 1.5를 Joomla 2.5, 3.X로 업그레이드하기 위한 MJUpgrade 소개
โดย wipaporn ศ 15 ก.พ. 2019 5:36 pm บอร์ด korean Language - 한국어
0
10
ศ 15 ก.พ. 2019 5:36 pm โดย wipaporn
MApplication Form Components를 소개한다. 구직 신청서는 웹사이트를 통해 작성된다.
โดย wipaporn ศ 15 ก.พ. 2019 5:27 pm บอร์ด korean Language - 한국어
0
9
ศ 15 ก.พ. 2019 5:27 pm โดย wipaporn
การรันTestCaseโดยใช้ตัวแปรเป็นตัวกำหนด ใน Python
โดย ธวัชชัย แสนหาญ ศ 15 ก.พ. 2019 5:20 pm บอร์ด Python Knowledge
0
11
ศ 15 ก.พ. 2019 5:20 pm โดย ธวัชชัย แสนหาญ
Joomla 웹사이트 방문수를 집계하기 위한 "Mod vinaora visitors counter" 소개
โดย wipaporn ศ 15 ก.พ. 2019 5:09 pm บอร์ด korean Language - 한국어
0
8
ศ 15 ก.พ. 2019 5:09 pm โดย wipaporn
유투브 동영상 및 클립매스 업로드를 위한 MVDO 플러그인 소개
โดย wipaporn ศ 15 ก.พ. 2019 4:45 pm บอร์ด korean Language - 한국어
0
9
ศ 15 ก.พ. 2019 4:45 pm โดย wipaporn
Joomla 3.x 홈페이지에서 사진 갤러리를 만들기 위한 MD 갤러리 컴포넌트 소개
โดย wipaporn ศ 15 ก.พ. 2019 4:36 pm บอร์ด korean Language - 한국어
0
12
ศ 15 ก.พ. 2019 4:36 pm โดย wipaporn