ให้เรตสมาชิก: 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

กระทู้ล่าสุดจากเว็บบอร์ด
หัวข้อกระทู้
ตอบ
เปิดดู
ล่าสุด
สร้างไฟล์ PDF ด้วยภาษา PHP
โดย kkk_k พฤ 17 ต.ค. 2019 1:08 am บอร์ด Programming - PHP
1
18
พฤ 17 ต.ค. 2019 1:23 am โดย mindphp
ถามเรื่องเช็คตัวเลขว่ามีเลขที่มากกว่า 10 เเต่น้อยกว่า 20 กี่ตัวยังไงครับ
โดย Golff Sinlapachai พ 16 ต.ค. 2019 6:19 pm บอร์ด Programming - PHP
1
23
พ 16 ต.ค. 2019 6:25 pm โดย mindphp
ฐานข้อมูลค่ะ
โดย sopida พ 16 ต.ค. 2019 3:37 pm บอร์ด Programming - PHP
1
11
พ 16 ต.ค. 2019 3:53 pm โดย thatsawan
replace หลายจุด และหลาย pattern พร้อมกันจบในการรันคำสั่งครั้งเดียว
โดย jataz2 พ 16 ต.ค. 2019 3:17 pm บอร์ด Programming - C/C++ & java & Python
0
8
พ 16 ต.ค. 2019 3:17 pm โดย jataz2
อัพเดพตัว Build Windows 10 แอพ Your Phone รับสายเรียกเข้า-โทรออกจาก สมาร์ทโฟนได้แล้ว
โดย chatee supasand อ 15 ต.ค. 2019 12:18 pm บอร์ด Microsoft Office Knowledge & line & Etc
0
27
อ 15 ต.ค. 2019 12:18 pm โดย chatee supasand
ตัวอย่างการสร้าง Service odoo13 บน Ubuntu 16.04
โดย mindphp ส 12 ต.ค. 2019 1:35 am บอร์ด Linux - Web Server
0
80
ส 12 ต.ค. 2019 1:35 am โดย mindphp
MJupgrade Joomla 1.5.26 > 3.9 ขึ้น Error: Could not connect to MySQL server.
โดย เห็ด อินโมชั่น ศ 11 ต.ค. 2019 3:30 pm บอร์ด Joomla Development
3
58
ศ 11 ต.ค. 2019 5:14 pm โดย เห็ด อินโมชั่น
MJupgrade Joomla 1.5.26 > 3.9 ขึ้น Error: Could not connect to MySQL server.
โดย เห็ด อินโมชั่น ศ 11 ต.ค. 2019 4:59 pm บอร์ด ปัญหาการใช้ phpBB3, SMF, Joomla, Wordpress, CMS CRM
7
2182
ส 12 ต.ค. 2019 3:35 am โดย mindphp
อยากทราบวิธีนับจำนวน id ที่ซ้ำกัน ครับ
โดย jamepiyawat ศ 11 ต.ค. 2019 5:06 pm บอร์ด SQL - Database
3
141
ศ 11 ต.ค. 2019 6:20 pm โดย jamepiyawat
การ Search ค้นหาข้อมูลของบอร์ด phpBB
โดย aninthana พฤ 10 ต.ค. 2019 6:46 pm บอร์ด Wordpress user Guide Knowledge
0
118
พฤ 10 ต.ค. 2019 6:46 pm โดย aninthana
ทำป้าย PopUp ด้วย Modal ใน Bootstrap เวอร์ชั่น 4
โดย jamepiyawat พฤ 10 ต.ค. 2019 5:20 pm บอร์ด Booststap Knowledge
0
125
พฤ 10 ต.ค. 2019 5:20 pm โดย jamepiyawat
ทำยังไงถึงจะไม่ให้แสดงเลข ID หน้า Alias ได้ครับ
โดย jamepiyawat พฤ 10 ต.ค. 2019 4:03 pm บอร์ด Joomla Development
1
43
พฤ 10 ต.ค. 2019 6:02 pm โดย tsukasaz
ทำไมผมถึงดึงข้อมูลชื่อหมวดหมู่ออกมาแสดงหน้าตั้งค่า module ไม่ได้ครับ
โดย jamepiyawat พฤ 10 ต.ค. 2019 3:47 pm บอร์ด Joomla Development
2
49
พฤ 10 ต.ค. 2019 6:36 pm โดย jamepiyawat
ตัวเลขด้านหน้าข้อความที่เราตั้ง Alias คืออะไรครับ
โดย jamepiyawat พฤ 10 ต.ค. 2019 11:36 am บอร์ด Joomla Development
5
116
พฤ 10 ต.ค. 2019 2:46 pm โดย mindphp
แก้ปัญหา Error Ignoring file '50unattended-upgrades.ucf-old' in directory บน Ubunto 16.04 ติดตั้ง apt-get
โดย mindphp พฤ 10 ต.ค. 2019 5:42 am บอร์ด Linux - Web Server
0
103
พฤ 10 ต.ค. 2019 5:42 am โดย mindphp
Q - สอบถามวิธี Upload file html ไปยัง web service โดยใช้คำสั่ง curl ใน PHP
โดย birdkritsna พ 09 ต.ค. 2019 3:42 pm บอร์ด Programming - PHP
6
121
พฤ 10 ต.ค. 2019 2:07 pm โดย birdkritsna
10 เเหล่งช๊อปปิ้งใรเชียงรายที่ต้องไปให้ได้
โดย nemo413 พ 09 ต.ค. 2019 1:04 pm บอร์ด พูดคุยเรื่องทั่วไป จับฉ่าย
0
119
พ 09 ต.ค. 2019 1:04 pm โดย nemo413
สอบถามครับ อยากได้ url ของลิงค์ ให้มาแสดงในช่อง ต้องทำยังไงครับ
โดย chatee supasand พ 09 ต.ค. 2019 12:22 pm บอร์ด Programming - C/C++ & java & Python
6
157
พ 09 ต.ค. 2019 1:41 pm โดย chatee supasand
Microsoft Word สามารถ แปลงไฟล์เสียง ให้เป็นข้อความได้แล้วใน Office 365
โดย chatee supasand พ 09 ต.ค. 2019 11:32 am บอร์ด Microsoft Office Knowledge & line & Etc
0
66
พ 09 ต.ค. 2019 11:32 am โดย chatee supasand
สอบถามการเขียนโค้ด กรอกข้อมูลหน้าแรก แล้วให้กดส่ง ไปยังหน้าที่สองครับผม
โดย Jakkrit Saengngoenon อ 08 ต.ค. 2019 1:40 pm บอร์ด Programming - PHP
1
67
อ 08 ต.ค. 2019 1:50 pm โดย mindphp