Redux Reducers ทำงานอย่างไร
เผยแพร่แล้ว: 2022-03-10state
ณ จุดใดจุดหนึ่ง คุณจะพบกับตัวลดขนาดที่แน่นอนที่สุด บทช่วยสอนนี้จะอธิบายแนวคิดของตัวลดขนาดและวิธีการทำงานโดยเฉพาะใน Reduxในบทช่วยสอนนี้ เราจะเรียนรู้แนวคิดของตัวลดขนาดและวิธีการทำงาน โดยเฉพาะในแอปพลิเคชัน React เพื่อให้เข้าใจและใช้งาน Redux ได้ดีขึ้น จำเป็นต้องมีความเข้าใจอย่างถ่องแท้เกี่ยวกับตัวลดขนาด ตัวลดขนาดให้วิธีการอัปเดตสถานะของแอปพลิเคชันโดยใช้การดำเนินการ เป็นส่วนสำคัญของไลบรารี Redux
บทช่วยสอนนี้มีไว้สำหรับนักพัฒนาที่ต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ Redux Reducers ความเข้าใจเกี่ยวกับ React และ Redux จะเป็นประโยชน์ ในตอนท้ายของบทช่วยสอน คุณควรมีความเข้าใจที่ดีขึ้นเกี่ยวกับบทบาทของ Reducers ใน Redux เราจะเขียนการสาธิตโค้ดและแอปพลิเคชันเพื่อทำความเข้าใจ Reducers ให้ดียิ่งขึ้นและผลกระทบต่อสถานะในแอปพลิเคชัน
ตัวลดคืออะไร
Reducer เป็นฟังก์ชันบริสุทธิ์ที่รับสถานะของแอปพลิเคชันและการดำเนินการเป็นอาร์กิวเมนต์และส่งคืนสถานะใหม่ ตัวอย่างเช่น ตัวลดการรับรองความถูกต้องสามารถใช้สถานะเริ่มต้นของแอปพลิเคชันในรูปแบบของออบเจกต์ว่างและการดำเนินการที่แจ้งว่าผู้ใช้ได้เข้าสู่ระบบและส่งคืนสถานะแอปพลิเคชันใหม่พร้อมกับผู้ใช้ที่เข้าสู่ระบบ
ฟังก์ชันบริสุทธิ์คือฟังก์ชันที่ไม่มีผลข้างเคียงและจะส่งกลับผลลัพธ์เดียวกันหากมีการส่งอาร์กิวเมนต์เดียวกันเข้ามา
ด้านล่างนี้เป็นตัวอย่างของฟังก์ชันบริสุทธิ์:
const add = (x, y) => x + y; add(2, 5);
ตัวอย่างข้างต้นคืนค่าตามอินพุต หากคุณผ่าน 2
และ 5
คุณจะได้รับ 7
เสมอ ตราบใดที่อินพุตเดียวกันไม่มีผลกับเอาต์พุตที่คุณได้รับ นั่นคือตัวอย่างของฟังก์ชันบริสุทธิ์
ด้านล่างนี้เป็นตัวอย่างของฟังก์ชันรีดิวเซอร์ที่อยู่ในสถานะและการดำเนินการ
const initialState = {}; const cartReducer = (state = initialState, action) => { // Do something here }
มากำหนดพารามิเตอร์สองตัวที่ตัวลดรับเข้ามา state
และ action
สถานะ
สถานะ คือข้อมูลที่คอมโพเนนต์ของคุณกำลังทำงานด้วย ซึ่งจะเก็บข้อมูลที่คอมโพเนนต์ต้องการและกำหนดสิ่งที่คอมโพเนนต์แสดงผล เมื่อวัตถุ state
เปลี่ยนแปลง ส่วนประกอบจะแสดงผลใหม่ หากสถานะแอปพลิเคชันได้รับการจัดการโดย Redux ตัวลดคือตำแหน่งที่การเปลี่ยนแปลงสถานะเกิดขึ้น
หนังบู๊
การ กระทำ คืออ็อบเจ็กต์ที่มีส่วนของข้อมูล เป็นแหล่งข้อมูลเดียวสำหรับร้าน Redux ที่จะอัปเดต ตัวลดอัปเดตร้านค้าตามค่าของ action.type
ที่นี่เราจะกำหนด action.type
เป็น ADD_TO_CART
ตามเอกสารอย่างเป็นทางการของ Redux การกระทำเป็นสิ่งเดียวที่ทำให้เกิดการเปลี่ยนแปลงในแอปพลิเคชัน Redux ซึ่งประกอบด้วยเพย์โหลดสำหรับการเปลี่ยนแปลงที่เก็บแอปพลิเคชัน การดำเนินการคือออบเจ็กต์ JavaScript ที่บอกให้ Redux ทราบถึงประเภทของการกระทำที่ต้องทำ โดยปกติจะถูกกำหนดเป็นฟังก์ชันดังที่แสดงด้านล่าง:
const action = { type: 'ADD_TO_CART', payload: { product: 'margarine', quantity: 4 } }
รหัสด้านบนเป็นค่า payload
ทั่วไปที่มีสิ่งที่ผู้ใช้ส่ง และจะถูกใช้เพื่ออัปเดตสถานะของแอปพลิเคชัน ดังที่คุณเห็นจากด้านบน ออบเจ็กต์แอคชันประกอบด้วยประเภทของแอคชันและเพย์โหลดออบเจ็กต์ที่จำเป็นสำหรับการดำเนินการเฉพาะนี้
กำลังอัปเดตสถานะโดยใช้ตัวลด
เพื่อแสดงวิธีการทำงานของตัวลดขนาด ให้ดูที่ตัวนับด้านล่าง:
const increaseAction = { type: 'INCREASE', }; const decreaseAction = { type: 'DECREASE' }; const countReducer = (state = 0, action) => { switch(action.type){ case INCREASE: return state + 1; case DECREASE : return state -1; default: return state; } };
ในโค้ดด้านบนนี้ increaseAction
และ decreaseAction
คือการดำเนินการที่ใช้ในตัวลดขนาดเพื่อกำหนดว่า state
จะอัปเดตเป็นสถานะใด ต่อไป เรามีฟังก์ชันรีดิวเซอร์ที่เรียกว่า countReducer
ซึ่ง action
และ state
เริ่มต้นที่มีค่าเป็น 0
หากค่าของ action.type
คือ INCREASE
เราจะคืนค่าสถานะใหม่ที่เพิ่มขึ้นทีละ 1 มิฉะนั้น หากเป็น DECREASE
สถานะใหม่ที่ลดลง 1 จะถูกส่งกลับ ในกรณีที่ไม่ได้หมายถึงเงื่อนไขเหล่านั้น เราจะคืนค่า state
กำลังอัปเดตสถานะโดยใช้ตัวลด: ตัวดำเนินการสเปรด
ไม่สามารถเปลี่ยนสถานะได้โดยตรง เพื่อสร้างหรืออัปเดตสถานะ เราสามารถใช้ตัวดำเนินการกระจาย JavaScript เพื่อให้แน่ใจว่าเราไม่ได้เปลี่ยนค่าของรัฐโดยตรง แต่จะส่งคืนวัตถุใหม่ที่มีสถานะที่ส่งผ่านไปยังมันและ เพย์โหลดของผู้ใช้
const contactAction = { type: 'GET_CONTACT', payload: ['0801234567', '0901234567'] }; const initialState = { contacts: [], contact: {}, }; export default function (state = initialState, action) { switch (action.type) { case GET_CONTACTS: return { ...state, contacts: action.payload, }; default: return state; }
ในโค้ดด้านบนนี้ เราใช้ตัวดำเนินการสเปรดเพื่อให้แน่ใจว่าเราจะไม่เปลี่ยนค่าสถานะโดยตรง ด้วยวิธีนี้ เราจะสามารถส่งคืนออบเจกต์ใหม่ที่เต็มไปด้วยสถานะที่ส่งผ่านไปยังมันและเพย์โหลดที่ส่งโดย ผู้ใช้ ด้วยการใช้ตัวดำเนินการกระจาย เราสามารถตรวจสอบให้แน่ใจว่าสถานะยังคงเหมือนเดิมในขณะที่เราเพิ่มรายการใหม่ทั้งหมดเข้าไป และยังแทนที่ฟิลด์ผู้ติดต่อในสถานะหากมีมาก่อน
Redux Reducers ใช้งานได้จริง — การสาธิต
เพื่อให้เข้าใจ Redux Reducers ได้ดีขึ้นและวิธีการทำงาน เราจะใช้แอปตัวค้นหารายละเอียดภาพยนตร์อย่างง่าย โดยสามารถดูโค้ดและเวอร์ชันการทำงานได้ที่นี่ใน Codesandbox ในการเริ่มต้น ไปที่เทอร์มินัลของคุณและเริ่มต้นแอปตอบโต้โดยใช้คำสั่งด้านล่าง:
create-react-app movie-detail-finder
เมื่อโปรเจ็กต์ของเราเริ่มต้นแล้ว ต่อไปเรามาติดตั้งแพ็คเกจที่จำเป็นสำหรับแอปพลิเคชันของเรากัน
npm i axios reactstrap react-redux redux redux-thunk
เมื่อติดตั้งแพ็คเกจแล้ว ให้เริ่มเซิร์ฟเวอร์การพัฒนาของเราโดยใช้คำสั่ง:
npm start
คำสั่งข้างต้นควรเริ่มต้นเซิร์ฟเวอร์การพัฒนาโครงการของเราในเบราว์เซอร์ของเรา ต่อไป ให้เปิดโครงการของเราในโปรแกรมแก้ไขข้อความที่เราเลือก ภายในโฟลเดอร์โครงการ src
ของเรา ให้ลบไฟล์ต่อไปนี้: App.css
, App.test.js
, serviceWorker.js
และ setupTests.js
ต่อไป มาลบโค้ดทั้งหมดที่อ้างอิงถึงไฟล์ที่ถูกลบใน App.js
ของเรา
สำหรับโครงการนี้ เราจะใช้ Open Movie Database API เพื่อรับข้อมูลภาพยนตร์ เนื้อหา และรูปภาพสำหรับแอปพลิเคชันของเรา นี่คือลิงก์ไปยัง API คุณจะต้องลงทะเบียนและรับคีย์การเข้าถึงเพื่อใช้งาน แอปพลิเคชัน เมื่อคุณทำเสร็จแล้ว ให้ดำเนินการกับแอปพลิเคชันของเราโดยการสร้างส่วนประกอบ
การสร้างส่วนประกอบแอพ
ขั้นแรก ภายในโฟลเดอร์ src
ของเราในไดเร็กทอรีโปรเจ็กต์ของเรา สร้างโฟลเดอร์ชื่อ components และภายในโฟลเดอร์ มาสร้างสองโฟลเดอร์ชื่อ Movie
และ Searchbar
คอมโพเนนต์ของเราควรมีลักษณะเหมือนภาพด้านล่าง:

การสร้างส่วนประกอบภาพยนตร์
มาสร้างองค์ประกอบ Movies
ซึ่งจะร่างโครงสร้างของรายละเอียดภาพยนตร์ที่เราจะได้รับจาก API ของเรา ในการดำเนินการนี้ ภายในโฟลเดอร์ Movies
ของส่วนประกอบของเรา ให้สร้างไฟล์ใหม่ Movie.js
จากนั้นให้สร้างองค์ประกอบตามคลาสสำหรับผลลัพธ์ API มาทำกันด้านล่าง
import React, { Component } from 'react'; import { Card, CardImg, CardText, CardBody, ListGroup, ListGroupItem, Badge } from 'reactstrap'; import styles from './Movie.module.css'; class Movie extends Component{ render(){ if(this.props.movie){ return ( <div className={styles.Movie}> <h3 className="text-center my-4"> Movie Name: {this.props.movie.Title} </h3> <Card className="text-primary bg-dark"> <CardImg className={styles.Img} top src={this.props.movie.Poster} alt={this.props.movie.Title}/> <CardBody> <ListGroup className="bg-dark"> <ListGroupItem> <Badge color="primary">Actors:</Badge> {this.props.movie.Actors} </ListGroupItem> <ListGroupItem> <Badge color="primary">Genre:</Badge> {this.props.movie.Genre} </ListGroupItem> <ListGroupItem> <Badge color="primary">Year:</Badge> {this.props.movie.Year} </ListGroupItem> <ListGroupItem> <Badge color="primary">Writer(s):</Badge> {this.props.movie.Writer} </ListGroupItem> <ListGroupItem> <Badge color="primary">IMDB Rating:</Badge> {this.props.movie.imdbRating}/10 </ListGroupItem> </ListGroup> <CardText className="mt-3 text-white"> <Badge color="secondary">Plot:</Badge> {this.props.movie.Plot} </CardText> </CardBody> </Card> </div> ) } return null } } export default Movie;
ในโค้ดด้านบน การใช้ส่วนประกอบจากแพ็คเกจ reactstrap
คุณสามารถตรวจสอบเอกสารประกอบได้ที่นี่ เราได้สร้างองค์ประกอบการ์ดที่ประกอบด้วยชื่อภาพยนตร์ รูปภาพ ประเภท นักแสดง ปี ผู้เขียนภาพยนตร์ การจัดเรต และพล็อต เพื่อให้ง่ายต่อการส่งข้อมูลจากส่วนประกอบนี้ เราได้สร้างข้อมูลเพื่อใช้เป็นอุปกรณ์ประกอบฉากไปยังส่วนประกอบอื่นๆ ต่อไป มาสร้างองค์ประกอบ Searchbar
ค้นหาของเรากัน

การสร้างส่วนประกอบของแถบค้นหาของเรา
คอมโพเนนต์ Searchbar
ของเราจะมีแถบค้นหาและส่วนประกอบปุ่มสำหรับค้นหาส่วนประกอบของภาพยนตร์ ให้ทำดังนี้
import React from 'react'; import styles from './Searchbar.module.css'; import { connect } from 'react-redux'; import { fetchMovie } from '../../actions'; import Movie from '../Movie/Movie'; class Searchbar extends React.Component{ render(){ return( <div className={styles.Form}> <div> <form onSubmit={this.formHandler}> <input type="text" placeholder="Movie Title" onChange={e => this.setState({title: e.target.value})} value={this.state.title}/> <button type="submit">Search</button> </form> </div> <Movie movie={this.props.movie}/> </div> ) } }
ในโค้ดด้านบนนี้ เรากำลังนำเข้าการ connect
จาก react-redux
ซึ่งใช้เพื่อเชื่อมต่อส่วนประกอบ React กับ Redux store จัดเตรียมส่วนประกอบด้วยข้อมูลจากสโตร์ และยังมีฟังก์ชันที่ใช้ในการส่งการกระทำไปยังสโตร์ ต่อไป เรานำเข้าองค์ประกอบ Movie
และฟังก์ชัน fetchMovie
จากการกระทำ
ต่อไป เรามีแท็กรูปแบบพร้อมช่องใส่สำหรับป้อนชื่อภาพยนตร์ของเรา โดยใช้เบ็ด setState
จาก React เราได้เพิ่มเหตุการณ์ onChange
และค่าที่จะตั้งค่าสถานะของ title
เป็นค่าที่ป้อนในกล่องป้อนข้อมูล เรามีแท็ก button
สำหรับค้นหาชื่อภาพยนตร์และใช้องค์ประกอบ Movie
ที่เรานำเข้า เราส่งต่อคุณสมบัติขององค์ประกอบเป็น props
ในผลการค้นหา
ต่อไปสำหรับเราคือการเขียนฟังก์ชันเพื่อส่งชื่อภาพยนตร์ของเราไปยัง API เพื่อส่งผลงานให้เรา เราต้องตั้งค่าสถานะเริ่มต้นของแอปพลิเคชันด้วย ลองทำกันด้านล่าง
class Searchbar extends React.Component{ state = { title: '' } formHandler = (event) => { event.preventDefault(); this.props.fetchMovie(this.state.title); this.setState({title: ''}); }
ที่นี่ เราตั้งค่าสถานะเริ่มต้นของแอปพลิเคชันเป็นสตริงว่าง เราสร้างฟังก์ชัน formHandler
ที่รับพารามิเตอร์เหตุการณ์และส่งผ่านฟังก์ชัน fetchMovie
จากการกระทำและการตั้งชื่อเป็นสถานะใหม่ของแอปพลิเคชัน เพื่อให้แอปพลิเคชันของเราสมบูรณ์ ให้ส่งออกส่วนประกอบนี้โดยใช้คุณสมบัติการเชื่อมต่อจาก react-redux
ในการดำเนินการนี้ เราจะใช้คุณสมบัติ react redux mapToStateProps
เพื่อเลือกส่วนของข้อมูลที่คอมโพเนนต์ของเราต้องการ คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับ mapToStateProps
ได้ที่นี่
const mapStateToProps = (state) => { return { movie: state.movie } } export default connect(mapStateToProps, { fetchMovie })(Searchbar)
มาเพิ่มสไตล์ให้กับแบบฟอร์มของเราโดยสร้างไฟล์ Searchbar.module.css
และเพิ่มสไตล์ด้านล่าง:
.Form{ margin: 3rem auto; width: 80%; height: 100%; } input{ display: block; height: 45px; border: none; width: 100%; border-radius: 0.5rem; outline: none; padding: 0 1rem; } input:focus, select:focus{ border: 2px rgb(16, 204, 179) solid; } .Form button{ display: block; background: rgb(16, 204, 179); padding: 0.7rem; border-radius: 0.5rem; width: 20%; margin-top: 0.7rem; color: #FFF; border: none; text-decoration: none; transition: all 0.5s; } button:hover{ opacity: 0.6; } @media(max-width: 700px){ input{ height: 40px; padding: 0 1rem; } .Form button{ width: 40%; padding: 0.6rem; } }
เมื่อเราดำเนินการตามข้างต้นแล้ว องค์ประกอบของแถบค้นหาควรมีลักษณะคล้ายกับรูปภาพด้านล่าง:

การสร้างการดำเนินการสำหรับแอปพลิเคชัน
ในองค์ประกอบนี้ เราจะตั้งค่าการดำเนินการ Redux สำหรับแอปพลิเคชันของเรา อันดับแรก ภายในไดเร็กทอรี src
สร้างโฟลเดอร์ชื่อ actions
และภายในโฟลเดอร์ เราจะสร้างไฟล์ index.js
ในที่นี้ เราจะสร้างฟังก์ชัน fetchMovie
ที่รับพารามิเตอร์ชื่อ และดึงภาพยนตร์จาก API โดยใช้ Axios ลองทำด้านล่าง:
import axios from 'axios'; export const fetchMovie = (title) => async (dispatch) => { const response = await axios.get( `https://cors-anywhere.herokuapp.com/https://www.omdbapi.com/?t=${title}&apikey=APIKEY`); dispatch({ type: 'FETCH_MOVIE', payload: response.data }) }
ในโค้ดด้านบน เรานำเข้า axios
และสร้างฟังก์ชันที่เรียกว่า fetchMovie
ซึ่งรับพารามิเตอร์ title
โดยใช้ async/await เพื่อให้เราสามารถส่งคำขอไปยังเซิร์ฟเวอร์ API ได้ เรามีฟังก์ชันการจัด dispatch
ที่ส่งออบเจ็กต์การดำเนินการที่ส่งไปยัง Redux ไปยัง Redux จากสิ่งที่เรามีข้างต้น เรากำลังดำเนินการกับประเภท FETCH_MOVIE
และเพย์โหลดที่มีการตอบสนองที่เราได้รับจาก API
หมายเหตุ: apikey
ในคำขอจะถูกแทนที่ด้วย apikey
ของคุณเองหลังจากลงทะเบียนที่ OmdbAPI
การสร้างตัวลดแอป
ในส่วนนี้ เราจะสร้างตัวลดขนาดสำหรับแอปพลิเคชันของเรา
const fetchMovieReducer = (state = null, action) => { switch(action.type){ case 'FETCH_MOVIE': return action.payload; default: return state; } } const rootReducer = (state, action) => { return { movie: fetchMovieReducer(state, action) } } export default rootReducer;
ในโค้ดด้านบน เราได้สร้าง fetchMovieReducer
ซึ่งรับสถานะเริ่มต้นเป็น null
และพารามิเตอร์ action
โดยใช้ตัวดำเนินการสวิตช์ สำหรับกรณี FETCH_MOVIE
เราจะคืนค่าของ action.payload
ซึ่งเป็นภาพยนตร์ที่เราได้รับจาก API หากการกระทำที่เราพยายามดำเนินการไม่อยู่ในตัวลด เราจะคืนค่าสถานะเริ่มต้นของเรา
ต่อไป เราได้สร้างฟังก์ชัน rootReducer
ที่จะยอมรับสถานะปัจจุบันและการดำเนินการเป็นอินพุตและส่งคืน fetchMovieReducer
เอามารวมกัน
ในส่วนนี้ เราจะทำแอปของเราให้เสร็จโดยสร้างที่เก็บ redux ใน index.js
มาทำกันด้านล่าง:
import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import App from './App'; import 'bootstrap/dist/css/bootstrap.min.css'; import './index.css'; import reducers from './reducers'; const store = createStore(reducers, applyMiddleware(thunk)) ReactDOM.render( <Provider store={store}> <> <App/> </> </Provider>, document.getElementById('root') )
ในโค้ดด้านบน เราได้สร้างที่ store
แอปพลิเคชันโดยใช้เมธอด createStore
โดยส่งตัวลดขนาดที่เราสร้างและมิดเดิลแวร์ Middlewares เป็นส่วนเสริมที่ช่วยให้เราสามารถปรับปรุงฟังก์ชันการทำงานของ Redux เรากำลังใช้ประโยชน์จากมิดเดิลแวร์ Redux Thunk โดยใช้ applyMiddleware
มิดเดิลแวร์ Redux Thunk จำเป็นสำหรับร้านค้าของเราในการอัปเดตแบบอะซิงโครนัส นี่เป็นสิ่งจำเป็นเพราะโดยค่าเริ่มต้น Redux จะอัปเดตร้านค้าพร้อมกัน
เพื่อให้แน่ใจว่าแอปพลิเคชันของเราทราบร้านค้าที่แน่นอนที่จะใช้ เราได้รวมแอปพลิเคชันของเราไว้ในองค์ประกอบของ Provider
และส่งผ่านร้านค้าเป็นอุปกรณ์ประกอบการ โดยการทำเช่นนี้ ส่วนประกอบอื่นๆ ในแอปพลิเคชันของเราสามารถเชื่อมต่อและแบ่งปันข้อมูลกับร้านค้าได้
มาเพิ่มสไตล์ให้กับไฟล์ index.css
*{ margin: 0; padding: 0; box-sizing: border-box; } body{ background: rgb(15, 10, 34); color: #FFF; height: 100vh; max-width: 100%; }
การแสดงผลและการทดสอบตัวค้นหารายละเอียดภาพยนตร์
ในส่วนนี้ เราจะสรุปแอปพลิเคชันของเราโดยแสดงแอปพลิเคชันของเราใน App.js
เพื่อทำสิ่งนี้ ให้สร้างองค์ประกอบตามคลาสที่ชื่อว่า App
และเริ่มต้นแถบค้นหาและช่องป้อนข้อมูลของเรา
import React from 'react'; import Searchbar from './components/Searchbar/Searchbar'; import styles from './App.module.css'; class App extends React.Component{ render(){ return( <div className={styles.App}> <h1 className={styles.Title}>Movies Search App</h1> <Searchbar/> </div> ) } } export default App;
ที่นี่ เราสร้างองค์ประกอบตามคลาสแอปด้วย h1
ที่ระบุว่าแอป Movie Search และเพิ่มองค์ประกอบ Searchbar
ค้นหาของเรา ใบสมัครของเราควรมีลักษณะเหมือนภาพด้านล่าง:

การสาธิตการทำงานมีอยู่ใน Codesandbox
บทสรุป
ตัวลดขนาดเป็นส่วนสำคัญของการจัดการสถานะ Redux ด้วยตัวลดขนาดเราสามารถเขียนฟังก์ชันที่บริสุทธิ์เพื่ออัปเดตพื้นที่เฉพาะของแอปพลิเคชัน Redux ของเราโดยไม่มีผลข้างเคียง เราได้เรียนรู้พื้นฐานของรีดิวเซอร์ Redux การใช้งาน และแนวคิดหลักของรีดิวเซอร์ สถานะ และอาร์กิวเมนต์
คุณสามารถดำเนินการเพิ่มเติมได้โดยดูเอกสารเกี่ยวกับตัวลด Redux ที่นี่ คุณสามารถใช้สิ่งนี้เพิ่มเติมและสร้างเพิ่มเติมเกี่ยวกับ Redux reducers แจ้งให้เราทราบว่าคุณสร้างอะไร
ทรัพยากร
- เอกสาร React-Redux
- เอกสาร Redux
-
connect()
ฟังก์ชั่น - ใช้ฟังก์ชัน
applyMiddleware