เกรียน-เรียน-React [Part-2]
TLDR ; การวิเคราะห์ปัญหาและทางแก้ไข Javascript, String Operator, Array Operator
ใครอยากProject เต็มๆ Fork แล้ว Pull git ไปได้เลยน่ะครับ
ขั้นตอนการทำของผมมีดังนี้ครับ
Step 1 — create-react-app
หากไม่เข้าใจว่าแปลว่าอะไรแปลว่าไมได้ดู Video ใน Part-1
Step 2 — ผมเลือกใช้ Bulma.io
Bulma.io คือ CSS สำเร็จรูปครับ คล้ายๆ Bootstrap แต่ตัด JQuery ทิ้ง สามารถเอามาใช้งานได้เลย เพียง Import bulma.css เข้ามาใน Project เราเป็นอันจบ วิธีใช้ดูตามตัวอย่างใน Website เค้าได้เลยครับ
มีแค่เรื่องเดียวที่พึงระวังครับ คือ ตัวอย่างเข้าทั้งหมด ภายใน tag ต่างๆ จะเป็นการเรียกใช้ด้วย class=”xxxxx” แต่ใน React ให้เราเรียนใช้โดยการเปลี่ยนเป็น className=”xxxxx” แทนครับ เช่นกันเนื้อหานี้อยู่ใน Video ใน Part-1
Import เข้ามาใช้ใน ทั้ง Project ได้เลยครับ วิธีใช้คือผมเอาไปยัดไว้ที่ index.js เลยครับก็จะได้ไม่ต้อง Import มาใช้ใน Component อื่นอีก
ปล.อันนี้คือผม ไม่ได้ลงแบบ npm น่ะครับเพราะเห็นว่ามันเป็น CSS เลยไม่อยากมองเป็น Package คิดว่าเอาเข้ามาดิบๆ แบบนี้เลยผม OK กว่า

Step 3 — ขึ้นโครง Web App
ผมได้ไป Copy หน้านึงมาเลยของ bulma เพราะขี้เกียจขึ้นโครงเอง
ตาม link ไป Copy Code กันมาได้เลยครับ ใส่ในส่วนของ return(“Paste code here”) ภายใน file App.js ของเรา

ข้อควรระวัง Copy มาใช้ไม่ได้เลย 100% น่ะครับจะขึ้น error ประมาณนี้

เหตุผลที่เป็นเช่นนี้เพราะ tag img ของเราต้องปิดด้วย /> เสมอครับ และ Tag อื่นๆ ด้วย ไม่อนุญาติให้เปิด โดยไม่มีการปิดครับ และก็อย่าลืมเปลี่ยน class เป็น className ลืมบอกไป Comment แบบ html ก็ห้ามใช้น่ะครับ <! — Comment — > ให้ลบทิ้งครับ
สุดท้าย Code ที่สมบูรณ์สำหรับเริ่มใช้งานจะเป็นดังนี้ครับ
import React, { Component } from ‘react’;
import ‘./App.css’;class App extends Component {render() {return (
<section className=”hero is-info is-large”>
<div className=”hero-head”>
<header className=”nav”>
<div className=”container”>
<div className=”nav-left”>
<a className=”nav-item”>
<img src=”images/bulma-type-white.png” alt=”Logo”/>
</a>
</div>
<span className=”nav-toggle”>
<span></span>
<span></span>
<span></span>
</span>
<div className=”nav-right nav-menu”>
<a className=”nav-item is-active”>
Home
</a>
<a className=”nav-item”>
Examples
</a>
<a className=”nav-item”>
Documentation
</a>
<span className=”nav-item”>
<a className=”button is-info is-inverted”>
<span className=”icon”>
<i className=”fa fa-github”></i>
</span>
<span>Download</span>
</a>
</span>
</div>
</div>
</header>
</div><div className=”hero-body”>
<div className=”container has-text-centered”>
<h1 className=”title”>
Title
</h1>
<h2 className=”subtitle”>
Subtitle
</h2>
</div>
</div><div className=”hero-foot”>
<nav className=”tabs is-boxed is-fullwidth”>
<div className=”container”>
<ul>
<li className=”is-active”><a>Overview</a></li>
<li><a>Modifiers</a></li>
<li><a>Grid</a></li>
<li><a>Elements</a></li>
<li><a>Components</a></li>
<li><a>Layout</a></li>
</ul>
</div>
</nav>
</div>
</section>
);
}
}export default App;
และนี้คือผลลัพธ์ที่ได้จากการพิมพ์ npm start ในเครื่องเรา

Step 4 — แก้ไขปัญหาที่คิดว่าง่ายที่สุดก่อน
ผมคิดว่าปัญหาที่ง่ายที่สุดปัญหาแรกคือ การทำให้ Space หายไปก่อน ทำไมผมมองว่าง่าย คือ ตอนนี้ปัญหาเราเยอะมากน่ะครับ ทั้งแยก Text แยกเลข แยกลำดับคน ลำดับของตา แต่ผมมองว่า Space เป็นปัญหามากเนืองจากถ้ามีมันอยู่น่าจะลำบากมากแน่ๆ เอามันมาติดๆ กันไว้ก่อนดีกว่าแล้วเรื่องจับมันแยกให้เอาไว้ที่หลัง
ก็ไปอ่าน Document ดูครับ มี methode ชื่อว่า trim() ให้ใช้ครับ
สรุปลองอ่านดูแล้ว ตอนแรกคิดว่าได้ อ่านไปอ่านมามันใช้ไมได้ครับ เหตุผลเพราะว่า trim() มันไม่สามารถลบ Space ระหว่างข้อความได้ ดังตัวอย่างดังนี้
console.log(" Hello World . ".trim()); // ผลที่ได้จริงๆคือ "Hello World ."// สิ่งที่ผมคาดหวังคือ "HelloWorld."
ก็เลยใช้ไม่ได้ครับ ก็หาต่อไป Google ไปเรื่อยครับ เช่น Search ว่า “How to remove space javascript” สุดท้ายไปๆ มาๆ เค้าให้ไปใช้ methode ที่ชื่อว่า replace() แทนครับ
ยอมรับเลยว่าอ่านแล้วงงมากครับ เลยไม่อ่าน ไปหาตัวอย่างมาใช้ก่อนแล้วค่อยมาเข้าใจทีหลัง ผมเลยใช้ท่านี้มาแก้ปัญหาครับ

บอกเลยครับ ผมอ่านไม่เข้าใจ แต่เดาได้ว่า ข้างบนน่าจะเป็นการค้นหาช่องว่างแล้วแทนที่ด้วยช่องเปล่าๆ ในความหมายก็คือลบ Space ที่ค้นเจอทุกตัวใน Text นั้นเอง
ผมก็ลอง Test กับ Data จริงๆ เลยครับ
อันนี้คือชุดข้อมูลที่ใช้ทดสอบครับ
1. ตี้ 0 ต้า -60 ชัช 602. ตี้ -100 ชัช -100 ต้า 2003. ตี้ -80 ชัช -20 ต้า 1004. ตี้ 40 ต้า -200 ชัช 1605. ตี้ -120 ชัช 0 ต้า 1206. ตี้ 0 ชัช -240 ต้า 240
แต่ก่อนจะลองได้มันต้องมี State , Components , function ที่เอาไว้เรียกซ่ะก่อน ก็จะ Copy Code ให้ดูเลยน่ะครับ คาดหวังว่าควรจะเข้าใจ คำศัพท์ที่ผมพูดด้านบนแล้วนะครับ ถ้าไม่เข้าใจไปย้อนดู Part-1 ใหม่ฝึกทำวนไปครับ ส่วน Project นี้จริงๆก็ไม่มีอะไรมากครับ มี TextArea 1 Component , Button 1 Component แล้วทุกครั้งที่ TextArea มีการเปลี่ยนแปลงเหตุการณ์ onChange เราจะไปเรียก function ที่เราเขียนไว้เพื่อให้ State ใน React มีการเปลี่ยนแปลง แล้ว เมื่อกดปุ่ม ที่เราสร้างมา ให้ show state ที่เปลี่ยนแปลงนั้น อาจจะมี TextField ไว้อีกสัก Component นึงไว้ Show ผลลัพธ์
อธิบายเพิ่มเติมละเอียดนิดนึงน่ะครับ เพื่อให้เห็นภาพ React นิดนึงน่ะครับ คำสั่งที่สำคัญๆ คือ setState ซึ่งเป็นการทำงาน Asynchronous กล่าวให้ง่ายกว่าเดิมคือ หากเราสั่ง setState ไปแล้ว ข้อมูลใน state จะยังไม่เปลี่ยนแปลงทันที กล่าวคือ ผมเลยใช้ OnChange ของ TextArea มาเพื่อทำการเอา ชุด String ไปใส่ใน Array ก่อน แล้ว OnClick ของ ปุ่มจึงทำแก้ไขข้อมูลอีกที ???
เมื่อ onChange ถูกทำงาน ให้ไปเรียก function handleSubmitReport
<textarea className=”textarea” placeholder=”Textarea” value={this.state.totalReport} onChange={this.handleSubmitReport}></textarea>ซึ่ง handleSubmitReport ก็คือ function ที่เราเขียนขึ้นมาเอง
handleSubmitReport = (event) => {
this.setState({totalReport: event.target.value});
this.setState({totalReportTrim: event.target.value.replace(/ /g,’’).replace(/\n/g,””).replace(/\d\./g,””)});
}
และหากเรากดปุ่ม Submit ก็จะไปเรียก function handleAnalyzeReport
<button className=”button is-primary” onClick={this.handleAnalyzeReport}>Submit</button>ซึ่งเราก็เขียนมันขึ้นมาเองเช่นกัน
handleAnalyzeReport = () => {
console.log(this.state.totalReportTrim);
}ให้สังเกตดีๆ แปลว่าทุกครั้งที่เรากดปุ่ม Submit จะมีการเปลี่ยนแปลงของข้อมูลในช่อง TextField ที่เราใส่อยู่แล้ว เพราะฉะนั้นจึงมั่นใจได้ว่าหากสั่ง setState ที่ onChange แล้ว เราจะสามารถดูผลที่เกิดขึ้นจาก onChange ใน Action onClick ได้เลย เพราะ onClick เกิดทีหลังเสมอ
Code Version สำเร็จแล้ว
import React, { Component } from ‘react’;
import ‘./App.css’;class App extends Component {state = {
totalReport : “”,
totalReportTrim : “”,
totalCurrentResult : []
}handleSubmitReport = (event) => {this.setState({totalReport: event.target.value});this.setState({totalReportTrim: event.target.value.replace(/ /g,’’)});
}
handleAnalyzeReport = () => {
console.log(this.state.totalReportTrim);
}
render() {return (
<section className=”hero is-info is-large”>
<div className=”hero-head”>
<header className=”nav”>
<div className=”container”>
<div className=”nav-left”>
<a className=”nav-item”>
<img src=”images/bulma-type-white.png” alt=”Logo”/>
</a>
</div>
<span className=”nav-toggle”>
<span></span>
<span></span>
<span></span>
</span>
<div className=”nav-right nav-menu”>
<a className=”nav-item is-active”>
Home
</a>
<a className=”nav-item”>
Examples
</a>
<a className=”nav-item”>
Documentation
</a>
<span className=”nav-item”>
<a className=”button is-info is-inverted”>
<span className=”icon”>
<i className=”fa fa-github”></i>
</span>
<span>Download</span>
</a>
</span>
</div>
</div>
</header>
</div><div className=”hero-body”>
<div className=”container has-text-centered”>
<p className=”control”>
<textarea className=”textarea” placeholder=”Textarea” value={this.state.totalReport} onChange={this.handleSubmitReport}></textarea>
</p>
<button className=”button is-primary” onClick={this.handleAnalyzeReport}>Submit</button>
</div>
</div><div className=”hero-foot”>
<nav className=”tabs is-boxed is-fullwidth”>
<div className=”container”>
<ul>
<li className=”is-active”><a>Overview</a></li>
<li><a>Modifiers</a></li>
<li><a>Grid</a></li>
<li><a>Elements</a></li>
<li><a>Components</a></li>
<li><a>Layout</a></li>
</ul>
</div>
</nav>
</div>
</section>
);
}
}export default App;
และหากเมื่อกดปุ่ม submit บวกกับเปิด Console ขึ้นมาดูจะได้ผลลัพธ์ดังนี้

ผลลัพธ์ที่ได้ก็น่าพอใจในระดับนึงครับ คือ สามารถ ลบ Space ที่มีระหว่างข้อมูลทิ้งได้หมด แต่มีปัญหาตามมาครับคือข้อมูลมันเว้นบรรทัด !!! ซึ่งก็ต้อง Search ต่อไปอีกว่าจะทำยังไงให้บรรทัดหายไป ก็ Google ไปเรื่อยครับ วนไปวนมา จนเจอ

คือเรื่องแบบนี้สอนกันไม่ได้ครับ คือ ถ้าคุณ Search บ่อยๆ ทำบ่อยๆ จะพอจับแนวทางได้ว่าคำตอบไหนใช้ได้ และคำตอบไหนที่ไม่น่าจะใช่ทางของเราต้องหมั่นฝึกฝนครับ ที่ผมเลือกคำตอบนี้เพราะ อ๋อ ผมรู้เพิ่มว่า replace มัน chain ต่อกันได้ ซึ่งผมตอนแรกผมไม่รู้ แต่คิดว่าอาจจะเป็นเพราะผมอ่าน document ไม่ละเอียดเองก็ได้ครับ ก็เลยเดาๆ Syntax ไปว่า เว้นบรรทัดน่าจะ \n แล้วแทนที่ด้วย ‘ ‘ (ค่าว่างๆ เหมือนกันก็น่าจะลบได้ Code จึงน่าจะออกมาประมาณนี้
this.setState({totalReportTrim: event.target.value.replace(/ /g,’’).replace(/\n/g,””)});ลองมาดูผลลัพธ์ที่ได้กันครับ

ก็ดูดีขึ้นมากครับ ข้อมูล Data Set ที่เพื่อนผมให้มาตอนนี้มันถูกเรียงตัวมาเป็นบรรทัดเดียวกันแล้วครับ ปัญหาใหม่ก็งอกมาอีกแล้วครับ คือ 1. 2. 3. 4. หรือคือรอบที่เล่นนั้นเองมันปนมากับชุดข้อมูล ซึ่งจริงๆ เราไม่อยากได้ เพราะว่าเราไม่สนว่าเล่นกันกี่รอบครับ แต่เราสนว่าผลรวมแล้วแต่ละคนมีแต้มเท่าไหร่ เพราะฉะนั้นจึงต้องหาทางกำจัดมันทิ้งไปให้ได้ก่อน ผม Search เยอะมากครับ ทำจนหลับไปประมาณ ตี 4 คือง่วงมากแล้วไม่ไหว ตื่นเช้าค่อยมาคิดใหม่
ตื่นมาก็นั่งคิดต่อ Search วนไปอีกครับ เพื่อหาทางแยก 1. 2. 3. 4. >>>> n. ออกมาให้ได้
Search ไป Search มาเหมือนจริงๆ ผมอ่านไม่ดีเองครับ
มันมีสิ่งที่เรียกว่า RegExp อยู่ ซึ่งตอนแรกผมงงว่ามันคืออะไร เอาจริงๆ น่ะคัรบ ตอนนี้ผมยัง งง อยู่เลย แต่ไป Search ดูมันเหมือนเป็น Pattern ในการเลือก String แบบ เฉพาะเจาะจงได้เลย ซึ่ง Click ไปที่ Link ใน Official MDN Network ก็มีให้อ่านชัดเจนครับ

อ่านไปอ่านมาเจอทางแก้แล้ว คิดว่าอ๋อ ไอ้ที่เรามั่วๆ มาตั้งแต่ตอนแรก ตั้งแต่ ตัดช่องว่าง , ตัดบรรทัด และ สุดท้ายยย อ้าวเห้ยยย มันสามารถตัด String แบบ สวยงามตามท้องเรื่องได้เลยนิหว่า !!! Code ในการ SetState ใหม่จึงเป็นดังนี้ครับ
this.setState({totalReportTrim: event.target.value.replace(/ /g,’’).replace(/\n/g,””).replace(/\d\./g,””)});จะสังเกตุเห็นว่าสิ่งที่ผมทำคือเพิ่ม .replace(/\d\./g.””) เข้าไป มันแปลว่า ผมให้มันค้นหา String ผมทั้งหมด ถ้าเจอ ตัวเลขแล้วตามด้วยจุด จะสั่งให้มันแทนที่ด้วยช่องว่างทันที เพราะฉะนั้นผลลัพธ์ที่ได้จากการทำแบบนี้จึงออกมาดังนี้
สุดท้ายจริงๆ อยากฝากให้ไปอ่านเนื้อหาที่จำเป็นและพื้นฐานของ React น่ะครับแม้ว่า Document เค้าจะอ่านยากซักนิดนึง เช่น Life Cycle ของมัน เป็นต้น
