ການເພີ່ມ Interactivity
ບາງສິ່ງເທິງໜ້າຈໍອັບເດດຕາມການປ້ອນຂໍ້ມູນຂອງຜູ້ໃຊ້. ຕົວຢ່າງ, ການຄິກ image gallery ຈະເປັນການສະຫຼັບຮູບພາບທີ່ໃຊ້ງານຢູ່. ໃນ React, ຂໍ້ມູນທີ່ປ່ຽນແປງເມື່ອເວລາຜ່ານໄປເອີ້ນວ່າ state. ທ່ານສາມາດເພີ່ມ state ໃຫ້ກັບ component ໃດກໍໄດ້, ແລະ ອັບເດດມັນເມື່ອຕ້ອງການ. ໃນບົດນີ້, ທ່ານຈະໄດ້ຮຽນຮູ້ວິທີຂຽນ component ທີ່ handle interaction, ອັບເດດ state ແລະ ສະແດງ output ຕ່າງໆເມື່ອເວລາຜ່ານໄປ.
In this chapter
ການຕອບສະໜອງຕໍ່ກັບ event
React ໃຫ້ທ່ານເພີ່ມ event handler ໃນ JSX ຂອງທ່ານ. Event handler ເປັນຟັງຊັ່ນຂອງທ່ານທີ່ຈະ trigger ໃຫ້ຕອບສະໜອງຕໍ່ການໂຕ້ຕອບຂອງຜູ້ໃຊ້ເຊັ່ນ: ການຄິກ, ການ hover, ການ focus ເທິງ form input ແລະ ອື່ນໆ.
Component built-in ເຊັ່ນ <button>
ຮອງຮັບສະເພາະ built-in browser event ເຊັ່ນ onClick
. ເຖິງຢ່າງໃດກໍຕາມ, ທ່ານຍັງສາມາດສ້າງ component ຂອງໂຕເອງ, ແລະ ໃຫ້ props event handler ຊື່ສະເພາະແອັບພິເຄຊັ່ນທີ່ທ່ານຕ້ອງການ.
export default function App() { return ( <Toolbar onPlayMovie={() => alert('Playing!')} onUploadImage={() => alert('Uploading!')} /> ); } function Toolbar({ onPlayMovie, onUploadImage }) { return ( <div> <Button onClick={onPlayMovie}> Play Movie </Button> <Button onClick={onUploadImage}> Upload Image </Button> </div> ); } function Button({ onClick, children }) { return ( <button onClick={onClick}> {children} </button> ); }
Ready to learn this topic?
ອ່ານ ການຕອບສະໜອງຕໍ່ກັບ Events ເພື່ອຮຽນຮູ້ວິທີການເພີ່ມ event handler.
Read MoreState: memory ຂອງ component
Component ມັກຈະຕ້ອງປ່ຽນສິ່ງທີ່ຢູ່ເທິງໜ້າຈໍອັນເປັນຜົນມາຈາກ interaction. ການພິມລົງໃນ form ຄວນອັບເດດປ່ອງຕື່ມຂໍ້ມູນ, ການຄິກ “next” ເທິງ carousel image ຄວນປ່ຽນຮູບພາບທີ່ຈະສະແດງ, ການຄິກ “buy” ໃສ່ສິນຄ້າລົງໃນກະຕ່າສິນຄ້າ. Component ຕ້ອງການ “ຈື່ຈຳ” ສິ່ງຕ່າງໆ: ຄ່າ input ຫຼ້າສຸດ, ຮູບຫຼ້າສຸດ, ກະຕ່າສິນຄ້າ. ໃນ React ໜ່ວຍຄວາມຈຳສະເພາະ component ນີ້ເອີ້ນວ່າ state.
ທ່ານສາມາດເພີ່ມ state ໃຫ້ກັບ component ດ້ວຍ useState
Hook. Hook ເປັນຟັງຊັ່ນພິເສດທີ່ຊ່ວຍໃຫ້ component ຂອງທ່ານໃຊ້ feature React (state ເປັນໜຶ່ງໃນ feature ເຫຼົ່ານັ້ນ). Hook useState
ໃຫ້ທ່ານປະກາດຕົວແປ state. ໃຊ້ state ເລີ່ມຕົ້ນ ແລະ return ຄູ່ຂອງຄ່າ: state ຫຼ້າສຸດ ແລະ ຟັງຊັ່ນ state setter ທີ່ໃຫ້ທ່ານອັບເດດມັນ.
const [index, setIndex] = useState(0);
const [showMore, setShowMore] = useState(false);
ນີ້ແມ່ນວິທີທີ່ gallery ຮູບພາບໃຊ້ ແລະ ອັບເດດ state ຕອນຄິກ:
import { useState } from 'react'; import { sculptureList } from './data.js'; export default function Gallery() { const [index, setIndex] = useState(0); const [showMore, setShowMore] = useState(false); const hasNext = index < sculptureList.length - 1; function handleNextClick() { if (hasNext) { setIndex(index + 1); } else { setIndex(0); } } function handleMoreClick() { setShowMore(!showMore); } let sculpture = sculptureList[index]; return ( <> <button onClick={handleNextClick}> Next </button> <h2> <i>{sculpture.name} </i> by {sculpture.artist} </h2> <h3> ({index + 1} of {sculptureList.length}) </h3> <button onClick={handleMoreClick}> {showMore ? 'Hide' : 'Show'} details </button> {showMore && <p>{sculpture.description}</p>} <img src={sculpture.url} alt={sculpture.alt} /> </> ); }
Ready to learn this topic?
ອ່ານ State: Memory ຂອງ Component ເພື່ອຮຽນຮູ້ວິທີຈົດຈຳຄ່າ ແລະ ອັບເດດມັນຕອນ interaction.
Read MoreRender ແລະ commit
ກ່ອນ Component ຂອງທ່ານຈະສະແດງເທິງໜ້າຈໍ, ມັນຕ້ອງ render ໂດຍ React. ການທຳຄວາມເຂົ້າໃຈຂັ້ນຕອນຕ່າງໆ ໃນຂະບວນການນີ້ຈະຊ່ວຍໃຫ້ທ່ານຄິດເຖິງວິທີທີ່ code execute ແລະ ອະທິບາຍລັກສະນະການເຮັດວຽກຂອງມັນໄດ້.
ຈິນຕະນາການວ່າ component ຂອງທ່ານແມ່ນພໍ່ຄົວໃຫ້ເຮືອນຄົວ, ກຳລັງເຮັດອາຫານຈານແຊບຈາກວັດຖຸດິບ. ໃນສະຖານະການສົມມຸດນີ້, React ແມ່ນພະນັກງານເສີບທີ່ສົ່ງຄຳຮ້ອງຈາກລູກຄ້າ ແລະ ນຳຄຳສັ່ງນັ້ນມາໃຫ້. ຂະບວນການຂໍ ແລະ ໃຫ້ບໍລິການ UI ມີສາມຂັ້ນຕອນ:
- ການ Trigger render (ສົ່ງອາຫານຕາມສັ່ງໄປທີເຮືອນຄົວ)
- ການ Render component (ກຽມອາຫານໃນເຮືອນຄົວ)
- ການ Commit to the DOM (ສົ່ງອາຫານໄປທີ່ໂຕະ)
Illustrated by Rachel Lee Nabors
State ເປັນ snapshot
ແຕກຕ່າງຈາກຕົວແປ JavaScript ທົ່ວໄປ, state React ຈະເຮັດວຽກຄືກັບ snapshot. ການຕັ້ງຄ່ານີ້ບໍ່ໄດ້ປ່ຽນຕົວແປ state ທີ່ທ່ານມີ, ແຕ່ມັນຈະ trigger ເພື່ອ render ໃໝ່ແທນ. ນີ້ອາດເປັນເລື່ອງປະຫຼາດໃຈໃນທຳອິດ!
console.log(count); // 0
setCount(count + 1); // Request a re-render with 1
console.log(count); // Still 0!
ລັກສະນະການເຮັດວຽກນີ້ຊ່ວຍໃຫ້ທ່ານຫຼີກຫຼ່ຽງ bug ໜ້ອຍໜຶ່ງ. ນີ້ແມ່ນແອັບແຊັດນ້ອຍ. ລອງເດົາເບິ່ງວ່າຈະເກີດຫຍັງຂຶ້ນຖ້າທ່ານກົດ “Send” ໃນຕອນທຳອິດ ແລະ ຈາກນັ້ນ ປ່ຽນຜູ້ຮັບເປັນ Bob. ຊື່ຂອງໃຜຈະປະກົດໃນ alert
ໃນອີກຫ້າວິນາທີຕໍ່ມາ?
import { useState } from 'react'; export default function Form() { const [to, setTo] = useState('Alice'); const [message, setMessage] = useState('Hello'); function handleSubmit(e) { e.preventDefault(); setTimeout(() => { alert(`You said ${message} to ${to}`); }, 5000); } return ( <form onSubmit={handleSubmit}> <label> To:{' '} <select value={to} onChange={e => setTo(e.target.value)}> <option value="Alice">Alice</option> <option value="Bob">Bob</option> </select> </label> <textarea placeholder="Message" value={message} onChange={e => setMessage(e.target.value)} /> <button type="submit">Send</button> </form> ); }
Ready to learn this topic?
ອ່ານ State ເປັນ Snapshot ເພື່ອຮຽນຮູ້ວ່າຍ້ອນຫຍັງ state ຈຶ່ງສະແດງເປັນ “fixed” ແລະ ບໍ່ມີການປ່ຽນແປງພາຍໃນ event handlers.
Read Moreການເຂົ້າຄິວອັບເດດ state
Component ນີ້ມີບັນຫາ: ການຄິກ “+3” ຈະເພີ່ມຄະແນນພຽງເທື່ອດຽວ.
import { useState } from 'react'; export default function Counter() { const [score, setScore] = useState(0); function increment() { setScore(score + 1); } return ( <> <button onClick={() => increment()}>+1</button> <button onClick={() => { increment(); increment(); increment(); }}>+3</button> <h1>Score: {score}</h1> </> ) }
State ເປັນ Snapshot ອະທິບາຍວ່າເປັນຫຍັງສິ່ງນີ້ຈຶ່ງເກີດຂຶ້ນ. State ການຕັ້ງຄ່າ request ການ render ໃໝ່, ແຕ່ຈະບໍ່ປ່ຽນແປງໃນ code ທີ່ກຳລັງເຮັດວຽກ. ສະນັ້ນ score
ຍັງເປັນ 0
ທັນທີຫຼັງຈາກທີ່ທ່ານເອີ້ນໃຊ້ setScore(score +1)
.
console.log(score); // 0
setScore(score + 1); // setScore(0 + 1);
console.log(score); // 0
setScore(score + 1); // setScore(0 + 1);
console.log(score); // 0
setScore(score + 1); // setScore(0 + 1);
console.log(score); // 0
ທ່ານສາມາດແກ້ໄຂບັນຫາໄດ້ໂດຍການສົ່ງ ຟັງຊັ່ນ updater ເມື່ອຕັ້ງຄ່າ state. ສັງເກດວິທີປ່ຽນແທນ setScore(score + 1)
ດ້ວຍ setScore(s => s + 1)
ຈະແກ້ໄຂປຸ່ມ “+3” ໄດ້ແນວໃດ. ສິ່ງນີ້ຈະເຮັດໃຫ້ທ່ານສາມາດຈັດການຄິວການອັບເດດຫຼາຍ state ໄດ້.
import { useState } from 'react'; export default function Counter() { const [score, setScore] = useState(0); function increment() { setScore(s => s + 1); } return ( <> <button onClick={() => increment()}>+1</button> <button onClick={() => { increment(); increment(); increment(); }}>+3</button> <h1>Score: {score}</h1> </> ) }
Ready to learn this topic?
ອ່ານ ການເຂົ້າຄິວອັບເດດ State ເພື່ອຮຽນຮຸ້ວິທີການຈັດຄິວຊຸດອັບເດດ state.
Read Moreການອັບເດດ object ໃນ state
State ສາມາດເກັບຄ່າ JavaScript ຊະນິດໃດກໍໄດ້, ລວມເຖິງ object. ແຕ່ທ່ານບໍ່ຄວນປ່ຽນ object ແລະ array ທີ່ທ່ານເກັບໃນ state React ໂດຍກົງ. ເມື່ອທ່ານຕ້ອງການອັບເດດ object ແລະ array, ທ່ານຕ້ອງສ້າງອັນໃໝ່ (ຫຼຶ ສຳເນົາຂອງສິ່ງທີ່ມີຢູ່) ຈາກນັ້ນອັບເດດ state ເພື່ອໃຊ້ສຳເນົານັ້ນ.
ໂດຍປົກະຕິ, ທ່ານຈະໃຊ້ syntax spread ...
ເພື່ອສຳເນົາ object ແລະ array ທີ່ທ່ານຕ້ອງການປ່ຽນ. ຕົວຢ່າງ, ການອັບເດດ object ທີ່ຊ້ອນກັນອາດມີລັກສະນະດັ່ງນີ້:
import { useState } from 'react'; export default function Form() { const [person, setPerson] = useState({ name: 'Niki de Saint Phalle', artwork: { title: 'Blue Nana', city: 'Hamburg', image: 'https://i.imgur.com/Sd1AgUOm.jpg', } }); function handleNameChange(e) { setPerson({ ...person, name: e.target.value }); } function handleTitleChange(e) { setPerson({ ...person, artwork: { ...person.artwork, title: e.target.value } }); } function handleCityChange(e) { setPerson({ ...person, artwork: { ...person.artwork, city: e.target.value } }); } function handleImageChange(e) { setPerson({ ...person, artwork: { ...person.artwork, image: e.target.value } }); } return ( <> <label> Name: <input value={person.name} onChange={handleNameChange} /> </label> <label> Title: <input value={person.artwork.title} onChange={handleTitleChange} /> </label> <label> City: <input value={person.artwork.city} onChange={handleCityChange} /> </label> <label> Image: <input value={person.artwork.image} onChange={handleImageChange} /> </label> <p> <i>{person.artwork.title}</i> {' by '} {person.name} <br /> (located in {person.artwork.city}) </p> <img src={person.artwork.image} alt={person.artwork.title} /> </> ); }
ຫາກການສຳເນົາ object ໃນ code ເປັນເລື່ອງນ່າເບື່ອ, ທ່ານສາມາດໃຊ້ library ເຊັ່ນ Immer ເພື່ອຫຼຸດການໃຊ້ code ຊໍ້າ:
import { useImmer } from 'use-immer'; export default function Form() { const [person, updatePerson] = useImmer({ name: 'Niki de Saint Phalle', artwork: { title: 'Blue Nana', city: 'Hamburg', image: 'https://i.imgur.com/Sd1AgUOm.jpg', } }); function handleNameChange(e) { updatePerson(draft => { draft.name = e.target.value; }); } function handleTitleChange(e) { updatePerson(draft => { draft.artwork.title = e.target.value; }); } function handleCityChange(e) { updatePerson(draft => { draft.artwork.city = e.target.value; }); } function handleImageChange(e) { updatePerson(draft => { draft.artwork.image = e.target.value; }); } return ( <> <label> Name: <input value={person.name} onChange={handleNameChange} /> </label> <label> Title: <input value={person.artwork.title} onChange={handleTitleChange} /> </label> <label> City: <input value={person.artwork.city} onChange={handleCityChange} /> </label> <label> Image: <input value={person.artwork.image} onChange={handleImageChange} /> </label> <p> <i>{person.artwork.title}</i> {' by '} {person.name} <br /> (located in {person.artwork.city}) </p> <img src={person.artwork.image} alt={person.artwork.title} /> </> ); }
Ready to learn this topic?
ອ່ານ ການອັບເດດ Object ໃນ State ເພື່ອຮຽນຮູ້ວິທີອັບເດດ object ຢ່າງຖືກຕ້ອງ.
Read Moreການອັບເດດ array ໃນ state
Array ເປັນ object JavaScript ທີ່ບໍ່ແນ່ນອນອີກປະເພດໜຶ່ງທີ່ທ່ານສາມາດເກັບໄວ້ໃນ state ແລະ ຄວນຖືເປັນ read-only. ແບບດຽວກັບ object, ເມື່ອທ່ານຕ້ອງການອັບເດດ array ທີ່ເກັບໄວ້ໃນ state, ທ່ານຕ້ອງສ້າງ array ໃໝ່ (ຫຼື ສຳເນົາຂອງ array ທີ່ມີຢູ່), ຈາກນັ້ນຕັ້ງ state ເພື່ອໃຊ້ array ໃໝ່:
import { useState } from 'react'; let nextId = 3; const initialList = [ { id: 0, title: 'Big Bellies', seen: false }, { id: 1, title: 'Lunar Landscape', seen: false }, { id: 2, title: 'Terracotta Army', seen: true }, ]; export default function BucketList() { const [list, setList] = useState( initialList ); function handleToggle(artworkId, nextSeen) { setList(list.map(artwork => { if (artwork.id === artworkId) { return { ...artwork, seen: nextSeen }; } else { return artwork; } })); } return ( <> <h1>Art Bucket List</h1> <h2>My list of art to see:</h2> <ItemList artworks={list} onToggle={handleToggle} /> </> ); } function ItemList({ artworks, onToggle }) { return ( <ul> {artworks.map(artwork => ( <li key={artwork.id}> <label> <input type="checkbox" checked={artwork.seen} onChange={e => { onToggle( artwork.id, e.target.checked ); }} /> {artwork.title} </label> </li> ))} </ul> ); }
ຖ້າການສຳເນົາ array ໃນ code ເປັນເລື່ອງນ່າເບື່ອ, ທ່ານສາມາດໃຊ້ library ເຊັ່ນ Immer ເພື່ອຫຼຸດການໃຊ້ code ຊໍ້າ:
import { useState } from 'react'; import { useImmer } from 'use-immer'; let nextId = 3; const initialList = [ { id: 0, title: 'Big Bellies', seen: false }, { id: 1, title: 'Lunar Landscape', seen: false }, { id: 2, title: 'Terracotta Army', seen: true }, ]; export default function BucketList() { const [list, updateList] = useImmer(initialList); function handleToggle(artworkId, nextSeen) { updateList(draft => { const artwork = draft.find(a => a.id === artworkId ); artwork.seen = nextSeen; }); } return ( <> <h1>Art Bucket List</h1> <h2>My list of art to see:</h2> <ItemList artworks={list} onToggle={handleToggle} /> </> ); } function ItemList({ artworks, onToggle }) { return ( <ul> {artworks.map(artwork => ( <li key={artwork.id}> <label> <input type="checkbox" checked={artwork.seen} onChange={e => { onToggle( artwork.id, e.target.checked ); }} /> {artwork.title} </label> </li> ))} </ul> ); }
Ready to learn this topic?
ອ່ານ ການອັບເດດ Array ໃນ State ເພື່ອຮຽນຮູ້ວິທີອັບເດດ arrat ຢ່າງຖືກຕ້ອງ.
Read Moreຕໍ່ໄປແມ່ນຫຍັງ?
ໄປທີ່ ການ Respond ຈາກ Events ເພີ່ມເລີ່ມອ່ານບົດນີ້ເທື່ອລະໜ້າ!
ຫຼື, ຖ້າທ່ານຄຸ້ນເຄີຍກັບຫົວຂໍ້ເຫຼົ່ານີ້ແລ້ວ, ລອງອ່ານກ່ຽວກັບ ການ manage State ເບິ່ງ