कंपनियां जो अपने अनुप्रयोगों के पूरे फ्रंट-एंड साइड का निर्माण करती हैं, अक्सर बैक-एंड बनाने के लिए रेल जैसे समान ढांचे का चयन करती हैं। कई वर्षों से, यह सबसे अच्छा और सबसे विश्वसनीय विकल्प रहा है।
आज, लगातार विकसित हो रहे फ्रंट-एंड ब्रह्मांड में, ढेर सारे पुस्तकालय और ढांचे, डेवलपर्स को बैक और फ्रंट-एंड दोनों के लिए अलग-अलग प्लेटफॉर्म चुनने और उन्हें आसानी से एकीकृत करने की अनुमति देते हैं।
रिएक्ट फ्रंट-एंड पैंजिया का टाइटन बन गया है। यदि आप रूबी ऑन रेल्स के साथ काम करते हैं, तो संभावना है कि आपको एक बार डिफ़ॉल्ट रेल पेजों को रिएक्ट कोड (या किसी अन्य फ्रंट फ्रेमवर्क) पर स्विच करने की आवश्यकता होगी। शायद, आप केवल रेल्स + रिएक्ट सुविधाओं से प्यार करते हैं और दोनों तकनीकों की शक्ति को एक ही ऐप में एकीकृत करना पसंद करेंगे।
और, यह ठीक है! इस लेख का उद्देश्य एक वास्तविक दुनिया के उदाहरण का पता लगाना है:एक सीआरयूडी एप्लिकेशन जो बीयर उत्पादों की एक सूची का प्रबंधन करता है। इसे शुरू में रेल के साथ बनाया जाएगा, और फिर रिएक्ट के साथ बनाया गया एक नया फ्रंट-एंड और एकीकृत किया जाएगा।
बीयर सीआरयूडी एप्लिकेशन।
कुछ चरणों में, आप रिएक्ट के मुख्य अंशों को समझेंगे कि रेल इसे कैसे अपनाती है, और आप अपनी भविष्य की परियोजनाओं में रेल और रिएक्ट दोनों को कैसे एकीकृत करना शुरू कर सकते हैं।
सेटअप
पूर्वापेक्षाओं के रूप में, आपको रूबी (और रेल), नोड.जेएस और यार्न के साथ एक वातावरण स्थापित करने की आवश्यकता है।
आप फ्रंट पैकेज को प्रबंधित करने के लिए npm को प्राथमिकता से चुन सकते हैं, लेकिन हम सादगी के लिए यार्न से चिपके रहेंगे।
अपनी पसंद के फ़ोल्डर में, निम्न कमांड चलाएँ:
rails new crud-rails-react
यह हमारी रेल परियोजना शुरू करेगा। फिर, अपने IDE में बनाए गए प्रोजेक्ट को खोलें और सीधे Gemfile . पर जाएं ।
हमें एक बग को ठीक करने की आवश्यकता है जो यह आदेश SQLite मणि के लिए उत्पन्न करता है। इसलिए, sqlite3
. का पता लगाना सुनिश्चित करें मणि और इसे निम्न में बदलें:
gem 'sqlite3', '~> 1.3.10'
यह डेटाबेस वर्जनिंग से संबंधित कुछ ज्ञात त्रुटियों को रोकेगा क्योंकि हम CRUD उदाहरण के लिए SQLite को डिफ़ॉल्ट डेटाबेस के रूप में उपयोग करेंगे।
हालांकि चिंता मत करो; अन्य डेटाबेस में, यह समस्या नहीं होगी।
डेटाबेस कॉन्फ़िग
मैं आमतौर पर चीजों को आधार से ऊपर की परतों तक बनाना पसंद करता हूं, तो चलिए डेटाबेस मॉडल बनाना शुरू करते हैं।
हमें केवल एक की आवश्यकता होगी, इसलिए कार्य के लिए रेल मचान से बेहतर कोई कमांड सुविधा नहीं है:
rails g scaffold Beer brand:string style:string country:string quantity:integer & rake db:migrate
यह मॉडल बहुत ही बुनियादी है, इसलिए जैसे ही आप जाते हैं अन्य विशेषताओं और प्रकारों को जोड़ने के लिए स्वतंत्र महसूस करें।
db/माइग्रेट . के अंदर फ़ोल्डर, एक नई फ़ाइल है जिसका नाम "_create_beers.rb . से समाप्त होता है " यह वह रिकॉर्ड है जिसे रेल ने हमारे लिए बीयर का प्रतिनिधित्व करने के लिए बनाया है।
मॉडल, बदले में, ऐप/मॉडल . के तहत जेनरेट किया जाएगा फ़ोल्डर। उन्हें वैसे ही रहने दें जैसे वे हैं और कोड की निम्नलिखित पंक्तियों को db/seeds.rb . में जोड़ें फ़ाइल:
Beer.create(brand: 'Double Stout', style: 'Stout', country: 'England', quantity: 54)
Beer.create(brand: 'Spaten', style: 'Helles', country: 'Germany', quantity: 3)
Beer.create(brand: 'Newcastle', style: 'Brown ale', country: 'UK', quantity: 12)
ऐप शुरू होने पर यह फ़ाइल डेटाबेस के लिए प्रारंभिक डेटा लोड संग्रहीत करेगी। उन्हें डेटाबेस में जारी करने के लिए, निम्न कमांड चलाएँ:
rake db:seed
इतना ही! अब, आपकी टेबल पर कुछ बीयर हैं ।
वेबपैकर सेटअप
वेबपैकर जावास्क्रिप्ट अनुप्रयोगों के लिए सबसे व्यापक रूप से उपयोग किए जाने वाले स्थिर मॉड्यूल बंडलर में से एक है। उसके कारण, मौजूदा एप्लिकेशन में रिएक्ट क्षमताओं को शामिल करने के लिए यह एकदम सही मेल है।
रेल हमें एक वेबपैकर बंडलर भी प्रदान करता है जो रेल के भीतर जावास्क्रिप्ट जैसे अनुप्रयोगों को प्रबंधित करने के लिए पूरी तरह से अनुकूलित है।
इसे स्थापित करने के लिए, अपने Gemfile . में दूसरी पंक्ति जोड़ें , इस प्रकार:
gem 'webpacker', '~> 4.3.x'
महान! यह एकमात्र रत्न है जिसे हमें संपूर्ण ऐप विकास के लिए जोड़ना होगा। यह केवल इसलिए संभव है क्योंकि हम यार्न को आगे की जिम्मेदारियां सौंप रहे हैं, जिसे बाद में इस लेख में सेट किया जाएगा।
अब, निम्न आदेश जारी करके अद्यतनों को स्थापित करने का समय आ गया है:
bundle install
bundle exec rake webpacker:install
bundle exec rake webpacker:install:react
सबसे पहले रेल डेवलपर्स द्वारा अच्छी तरह से जाना जाता है। हम केवल वेबपैकर सहित सभी निर्भरताओं को स्थापित कर रहे हैं।
एक बार वेबपैकर स्थापित हो जाने के बाद, हम वेबपैकर निर्भरता, साथ ही रिएक्ट वाले को स्थापित करने के लिए रेक के माध्यम से इसके आदेशों का अनुकरण कर सकते हैं।
यह एक बहुत ही महत्वपूर्ण कदम है क्योंकि यह वह जगह है जहां वेबपैकर यह सुनिश्चित करेगा कि आपकी सभी जावास्क्रिप्ट निर्भरताएं रेल पर्यावरण पर ठीक से सेट हैं, इसलिए इसे छोड़ें या उन्हें सीधे चलाने का प्रयास न करें जैसा कि आप आमतौर पर एनपीएम या यार्न के साथ करते हैं, ठीक है?पी>
जब आदेश पूर्ण हो जाते हैं, तो कुछ फ़ोल्डर और फ़ाइलें (जैसे node_modules
.) और package.json
) भी बनाया जाएगा।
फ्रंट-एंड सेटअप
हमने अब तक जो भी सेटिंग्स की हैं, वे सीआरयूडी एप्लिकेशन को केवल रेल के साथ काम करने के लिए पर्याप्त हैं। यदि आप rails s
. के माध्यम से रेल सर्वर प्रारंभ करते हैं आदेश, यह परिणाम होगा:
रेल ऑटो-जेनरेटेड बियर सीआरयूडी।
हालांकि, हम रिएक्ट के साथ अपना सीआरयूडी चाहते हैं।
सबसे पहले, आपको यह सुनिश्चित करने की आवश्यकता है कि सभी आवश्यक फ़्रंट-एंड निर्भरताएँ यार्न के माध्यम से कॉन्फ़िगर की गई हैं:
- प्रतिक्रिया
- रिएक्ट ऐप में नेविगेशन से निपटने के लिए रिएक्ट राउटर
- रेडी-टू-यूज़ रिएक्ट घटकों के लिए चींटी का डिज़ाइन
चींटी डिजाइन (एंटीडी के रूप में जाना जाता है) उद्यम-स्तर के अनुप्रयोगों के लिए एक समृद्ध ओपन-सोर्स लाइब्रेरी है। यह उच्च अनुकूलन योग्य रिएक्ट घटकों का एक समूह प्रदान करता है जो वेब ऐप्स के विकास को बहुत सरल करता है।
सब कुछ स्थापित करने के लिए, निम्न आदेश चलाएँ:
yarn add antd react-router-dom
हमें स्पष्ट रूप से react
जोड़ने की आवश्यकता नहीं है react-router-dom
. के बाद से पुस्तकालय करेंगे।
इस समय, जब आप package.json खोलते हैं फ़ाइल, यह स्वतः उत्पन्न सामग्री होगी:
{
"dependencies": {
"@babel/preset-react": "^7.12.1",
"@rails/webpacker": "4.3.0",
"antd": "^4.7.2",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"prop-types": "^15.7.2",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-router-dom": "^5.2.0"
},
"devDependencies": {
"webpack-dev-server": "^3.11.0"
}
}
रेल-रिएक्शन कॉम्बो के लिए यह सबसे बुनियादी सेटअप है। इसलिए, हमें कोड की ओर बढ़ना अच्छा लगता है।
रेल पक्ष को अनुकूलित करना
आगे बढ़ने से पहले कुछ महत्वपूर्ण कार्यों को रेल की तरफ से संबोधित किया जाना चाहिए।
सबसे पहले, हमें उस नियंत्रक को परिभाषित करने की आवश्यकता है जो पृष्ठ पुनर्निर्देशन को केंद्रीकृत करेगा। चूंकि हम एक सिंगल-पेज एप्लिकेशन (एसपीए) बना रहे हैं, केवल एक नियंत्रक की जरूरत है, जो पहले से ही बनाया गया था:BeersController
।
इसे एप्लिकेशन/नियंत्रकों . के अंतर्गत खोलें फ़ोल्डर और उसकी सामग्री को इस प्रकार बदलें:
class BeersController < ApplicationController
def index
end
end
चिंता मत करो; हमारे द्वारा हटाए गए सभी कोड अगले नियंत्रक में बनाए जाएंगे जिसे बनाया जाना है।
इस नियंत्रक का एकमात्र कार्य रेल से प्रतिक्रिया के लिए एक सीधा मार्ग प्रदान करना है, यही कारण है कि हम केवल index
सेट कर रहे हैं विधि।
इससे सीधे जुड़ने के लिए, आइए routes.rb खोलें कॉन्फ़िगरेशन . के अंतर्गत फ़ाइल फ़ोल्डर और उसकी सामग्री को निम्न में बदलें:
Rails.application.routes.draw do
root 'beers#index'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
नया root
नोट करें विन्यास हां, हम रूट के एंडपॉइंट को beers
. से मैप कर रहे हैं अनुक्रमणिका विधि।
आपको index.html.erb . को भी खाली करना होगा ऐप/व्यू/बीयर . के अंदर फ़ाइल करें फ़ोल्डर क्योंकि हम नहीं चाहते कि कोई भी रेल वेब सामग्री प्रस्तुत की जाए। यह एक तरकीब है जिसका उपयोग हम रेल को केवल रिएक्ट कोड प्रदर्शित करने के लिए बाध्य करने के लिए कर सकते हैं।
बीयर एपीआई
अब, बीयर एपीआई निर्माण पर चलते हैं। एपीआई संरचना व्यावहारिक रूप से BeersController
. जैसी ही होगी लेकिन कुछ मामूली बदलाव के साथ। इसे बनाने के लिए, निम्न कमांड चलाएँ:
rails generate controller api/v1/Beers
वर्जनिंग सिस्टम का उपयोग करके इसे बनाना सुनिश्चित करें। यह आपको भविष्य में अपना एपीआई विकसित करने और इसे सामान्य नियंत्रकों से अलग करने की अनुमति देगा।
अब, app/controllers/api/v1/beers_controller.rb खोलें फ़ाइल करें और कोड को निम्न से बदलें:
class Api::V1::BeersController < ApplicationController
before_action :set_beer, only: [:show, :edit, :update, :destroy]
# GET /beers
# GET /beers.json
def index
@beers = Beer.all.order(brand: :asc)
render json: @beers
end
# GET /beers/1
# GET /beers/1.json
def show
if @beer
render json: @beer
else
render json: @beer.errors
end
end
# GET /beers/new
def new
@beer = Beer.new
end
# GET /beers/1/edit
def edit
end
# POST /beers
# POST /beers.json
def create
@beer = Beer.new(beer_params)
if @beer.save
render json: @beer
else
render json: @beer.errors
end
end
# PATCH/PUT /beers/1
# PATCH/PUT /beers/1.json
def update
end
# DELETE /beers/1
# DELETE /beers/1.json
def destroy
@beer.destroy
render json: { notice: 'Beer was successfully removed.' }
end
private
# Use callbacks to share common setup or constraints between actions.
def set_beer
@beer = Beer.find(params[:id])
end
# Only allow a list of trusted parameters through.
def beer_params
params.permit(:brand, :style, :country, :quantity)
end
end
अधिकांश संचालन पिछले नियंत्रक से पुनर्नवीनीकरण किए गए थे।
before_action
स्निपेट id
. के अनुसार उचित बियर ऑब्जेक्ट को पुनर्प्राप्त करने का ध्यान रखेगा अनुरोध के भीतर पैरामीटर। केवल :only
. के बाद सरणी में रखे गए ऑपरेशन क्लॉज को इस ऑटो-रिकवरी फीचर की जरूरत होगी।
शेष विधियां सीआरयूडी के प्रत्येक संचालन के बराबर हैं। बस अपने अनुरोधों के जवाब के रूप में हमेशा JSON को वापस करना याद रखें क्योंकि यही वह प्रारूप है जिसका उपयोग हम अपने रिएक्ट घटकों के भीतर करेंगे।
अंत में, आपको config/routes.rb . को अनुकूलित करने की आवश्यकता होगी नए बनाए गए मार्गों को फिर से शामिल करने के लिए। इसलिए, फ़ाइल की सामग्री को निम्न में बदलना सुनिश्चित करें:
Rails.application.routes.draw do
namespace :api do
namespace :v1 do
get 'beers/index'
post 'beers/create'
delete 'beers/:id', to: 'beers#destroy'
end
end
root 'beers#index'
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
नष्ट करने का मार्ग दर्शाता है कि destroy
. के लिए मैप कैसे किया जाता है विधि अगर यह स्पष्ट रूप से पथ में सेट नहीं है।
प्रतिक्रिया घटक
रिएक्ट घटकों के माध्यम से काम करता है, जो वेब एप्लिकेशन के बिल्डिंग ब्लॉक्स की तरह काम करता है। प्रत्येक व्यक्ति एक या अधिक कार्य करता है जो एक संदर्भ के रूप में समझ में आता है।
संक्षेप में, एक घटक जावास्क्रिप्ट वर्ग या फ़ंक्शन से बना होता है जो पैरामीटर के रूप में गुण प्राप्त कर सकता है, इसके भीतर व्यावसायिक तर्क संसाधित कर सकता है, और अंत में, स्क्रीन के एक हिस्से का प्रतिनिधित्व करने वाला एक कार्यात्मक UI घटक लौटा सकता है।
हमारे द्वारा बनाए जाने वाले अगले उदाहरणों से निकाले गए निम्नलिखित कोड स्निपेट को लें:
<Layout>
<Header />
<Content>...</Content>
<Footer>Honeybadger ©2020.</Footer>
</Layout>
हां, रिएक्ट घटक जेएसएक्स (जावास्क्रिप्ट एक्सएमएल) नामक एक कस्टम मार्कअप भाषा का उपयोग करते हैं जो एचटीएमएल से काफी मिलता-जुलता है। सभी HTML टैग JSX फ़ाइलों में भी उपलब्ध हैं। आप यहां JSX पर अधिक पढ़ सकते हैं।
ऊपर दिया गया उदाहरण दिखाता है कि antd एक संरचनात्मक लेआउट घटक के साथ कैसे व्यवहार करता है। घटक अन्य घटकों से बने होते हैं और एक दूसरे के ऊपर ढेर हो जाते हैं, एक संपूर्ण रचना करते हैं। कुछ गुण प्राप्त करते हैं (वैकल्पिक या नहीं), और कुछ में आंतरिक सामग्री हो सकती है।
घटक वर्ग- या कार्य-आधारित हो सकते हैं।
कक्षा के घटक
क्लास-आधारित घटक सामान्य JavaScript क्लास की तरह बनाए जाते हैं, जैसा कि नीचे दिखाया गया है:
class Beers extends React.Component {}
वे React.Component
. से इनहेरिट करते हैं वर्ग, एक जीवनचक्र है, और आरंभीकरण, प्रतिपादन, और चरणों को नष्ट करने से पहले कोड को निष्पादित करने के लिए उपयोग के तरीके प्रदान करता है।
हालांकि, सबसे महत्वपूर्ण (और आवश्यक) तरीका है render()
, जिसे हर बार घटक के अद्यतन होने पर कहा जाता है।
कार्यात्मक घटक
कार्यात्मक घटक ES6 के एरो फ़ंक्शन का उपयोग करते हैं और सिंटैक्स और जटिलता के संदर्भ में रिएक्ट घटकों को सरल बनाते हैं।
वही beers
उपरोक्त घटक को एक फ़ंक्शन में निम्नानुसार दर्शाया जाएगा:
const Beers = () => <div>My Beers</div>;
यह बहुत आसान है, है ना?
प्रतिक्रिया सेट करना
हमने रेल इंडेक्स पेज को पहले ही खाली कर दिया है। अब, हम रेल को बताएंगे कि उसे रिएक्ट को अपना डिफ़ॉल्ट फ्रंट-एंड बनाने की आवश्यकता है।
इसे प्राप्त करने के लिए, आपको कोड की निम्न पंक्ति को <head>
. में जोड़ना होगा आपके app/views/layouts/application.html.erb . का टैग फ़ाइल:
<%= javascript_pack_tag 'index' %>
यह हमारे एप्लिकेशन हेडर में जावास्क्रिप्ट पैक जोड़ देगा, जिससे सभी जावास्क्रिप्ट फाइलें, रिएक्ट सहित, को इंडेक्स के भीतर निष्पादित किया जाएगा। पेज.
हमें यह सुनिश्चित करने की आवश्यकता है कि index.jsx फ़ाइल का नाम वही है क्योंकि यह आयात पैक पर इंगित किया गया है।
इस उद्देश्य के लिए, ऑटोजेनरेटेड app/javascript/packs/hello_react.jsx का नाम बदलें। index.jsx . पर फ़ाइल करें ।
फिर, कोड को निम्नलिखित से बदलें:
import React from "react";
import { render } from "react-dom";
import App from "../components/App";
document.addEventListener("DOMContentLoaded", () => {
render(<App />, document.body.appendChild(document.createElement("div")));
});
इस फ़ाइल को रिएक्ट एप्लिकेशन फ़ाइल के लिए गलती न करें, क्योंकि यह केवल वह फ़ाइल है जो ReactDOM के render
के माध्यम से पूरे React ऐप पदानुक्रम को DOM में लोड करेगी। समारोह।
आमतौर पर, प्रत्येक रिएक्ट एप्लिकेशन एक index.js . से शुरू होता है फ़ाइल जो आवश्यक सभी चीज़ों को लोड करती है, जिसमें स्वयं प्रतिक्रिया भी शामिल है।
App
टैग हमारे पदानुक्रम के शीर्ष घटक को मैप करता है। तो, चलिए इसे index.jsx . के रूप में बनाते हैं जावास्क्रिप्ट/घटकों . के अंतर्गत फ़ोल्डर (यदि वे अभी तक मौजूद नहीं हैं तो मैन्युअल रूप से फ़ोल्डर बनाएं) और उसमें निम्न कोड डालें:
import React from "react";
import Routes from "../routes/index";
import "antd/dist/antd.css";
export default () => <>{Routes}</>;
वैकल्पिक रूप से, आप antd CSS फ़ाइल को index.jsx . में आयात कर सकते हैं . कोई भी तरीका काम करेगा।
मार्गों की सूची मार्गों . के अंतर्गत रखी गई है फ़ोल्डर। वे रिएक्ट राउटर लाइब्रेरी से निकाले गए हैं, जो हमारे लिए अधिकांश मेहनत करता है। यह इसकी सामग्री है:
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import Home from "../components/Home";
export default (
<Router>
<Switch>
<Route path="/" exact component={Home} />
</Switch>
</Router>
);
आपके प्रत्येक मार्ग को एक अलग root
. के भीतर मैप किया जाना चाहिए उपनाम। path
पैरामीटर प्रत्येक रूट एंडपॉइंट के यूआरआई से मेल खाना चाहिए, जबकि component
परम उस घटक को इंगित करता है जिस पर रिएक्ट राउटर को अनुरोध को पुनर्निर्देशित करना चाहिए।
याद रखें कि हमारे पास हमारे एसपीए के लिए एक ही मार्ग होगा। यदि आप /बीयर्स . को मैप करना चाहते हैं तो आप यहां अन्य पथ भी जोड़ सकते हैं उदाहरण के लिए, बियर की सूची के लिए, लेकिन हम इसे सरल रखेंगे।
साथ ही, ध्यान दें कि हम Home
आयात कर रहे हैं यहां घटक, जो अभी तक मौजूद नहीं है। तो, चलिए इसे Home.jsx . के रूप में बनाते हैं घटकों . के अंतर्गत फ़ोल्डर। फिर, इसमें निम्न कोड जोड़ें:
import { Layout } from "antd";
import React from "react";
import Beers from "./Beers";
import Header from "./Header";
const { Content, Footer } = Layout;
export default () => (
<Layout className="layout">
<Header />
<Content style={{ padding: "0 50px" }}>
<div className="site-layout-content" style={{ margin: "100px auto" }}>
<h1>Beer Catalog</h1>
<Beers />
</div>
</Content>
<Footer style={{ textAlign: "center" }}>Honeybadger ©2020.</Footer>
</Layout>
);
जब रिएक्ट घटकों की बात आती है, तो मैं उन्हें ऊपर से नीचे तक बनाना पसंद करता हूं। इस तरह, आप ऐप को समग्र रूप से काम करने के लिए सभी आवश्यक घटकों पर एक समग्र नज़र डाल सकते हैं।
होम कंपोनेंट एक असेंबलर की तरह व्यवहार करता है; यह ऐप के अन्य सभी घटकों को समायोजित करता है, जैसे Layout
, Header
, Content,
और Footer
।
इन टुकड़ों में से प्रत्येक कहाँ से आ रहा है, यह ठीक से भेद करना महत्वपूर्ण है। Antd आपकी स्क्रीन को कंपोज़ करने के लिए तैयार घटकों का एक समूह प्रदान करता है, जैसे कि लेआउट, सामग्री और पाद लेख।
वे मुख्य रूप से पृष्ठ भागों की संरचना पर ध्यान केंद्रित करते हैं, लेकिन कुछ भी अंतर्निहित सीएसएस शैलियों की पेशकश करते हैं, जो हमें बेहतर रूप से लाभान्वित करेंगे।
शीर्षक घटक
Header.jsx घटक फ़ाइल, जिसे जावास्क्रिप्ट/घटकों में भी बनाया जाना चाहिए फ़ोल्डर, हेडर की सामग्री रखेगा। इसमें एक साधारण एएनटीडी मेनू और हनीबैगर लोगो के साथ एक डिव शामिल है, जैसा कि नीचे दिखाया गया है:
Antd मेनू आइटम।
नीचे, आप Header.jsx . में डालने के लिए कोड ढूंढ सकते हैं :
import React from "react";
import { Layout, Menu } from "antd";
const { Header } = Layout;
export default () => (
<Header>
<div className="logo" />
<Menu theme="dark" mode="horizontal" defaultSelectedKeys={["1"]}>
<Menu.Item key="1">Home</Menu.Item>
<Menu.Item key="2">Our Services</Menu.Item>
<Menu.Item key="3">Contact</Menu.Item>
</Menu>
</Header>
);
Antd मेनू घटक उपयोग करने के लिए काफी सरल है, लेकिन उपलब्ध अनुकूलन विकल्पों के संदर्भ में व्यापक है, जिससे हमें नेविगेशन ड्रॉअर, ड्रॉप-डाउन, समूह और उपसमूह बनाने की अनुमति मिलती है।
ध्यान दें कि हम defaultSelectedKeys
प्रदान कर रहे हैं , एक सरणी जो मेनू को बताती है कि कौन से आइटम सक्रिय हैं।
हमारे मेनू कहीं भी नेविगेट नहीं करेंगे; वे केवल लुक-एंड-फील को पूरा करने के लिए स्क्रीन पर कब्जा कर लेंगे। तो, चलिए beers
पर चलते हैं घटक।
बीयर्स घटक
यह घटक बियर की सूची, और तालिका के भीतर उपलब्ध कार्रवाइयों, जैसे हटाना, डेटा पृष्ठांकन, और तालिका पुनः लोड करने पर केंद्रित है।
प्रतिक्रिया क्रियाओं और घटकों का दृश्य प्रतिनिधित्व।
ऊपर की छवि पर एक नज़र डालें। हमने घटकों और कार्यों को निचले स्तर पर विभाजित किया है, ताकि आप बेहतर ढंग से समझ सकें कि यहां क्या किया जाएगा।
प्रतिक्रिया स्थिति
प्रतिक्रिया घटक एक state
. के साथ बनाए जाते हैं वस्तु। यह ऑब्जेक्ट सीधे दिए गए घटक से जुड़े एक स्टोर के रूप में कार्य करता है। प्रत्येक घटक का अपना state
होता है ऑब्जेक्ट, और हर बार जब आप राज्य बदलते हैं, तो घटक फिर से प्रस्तुत हो जाता है।
हमारे beers
. की पहली क्रिया घटक एक टेबल पर लिस्टिंग प्रदर्शित करना है। इस उद्देश्य के लिए, हमें इस सूची को एक सरणी में रखना होगा:
state = {
beers: [],
};
बीयर्स लिस्टिंग
इस सरणी को खिलाने के लिए, हमें पहले बनाए गए एपीआई नियंत्रक से सूची को पुनः प्राप्त करना होगा। उस फ़ंक्शन की समीक्षा करें जो इसे पुनः प्राप्त करेगा:
loadBeers = () => {
const url = "api/v1/beers/index";
fetch(url)
.then((data) => {
if (data.ok) {
return data.json();
}
throw new Error("Network error.");
})
.then((data) => {
data.forEach((beer) => {
const newEl = {
key: beer.id,
id: beer.id,
brand: beer.brand,
style: beer.style,
country: beer.country,
quantity: beer.quantity,
};
this.setState((prevState) => ({
beers: [...prevState.beers, newEl],
}));
});
})
.catch((err) => message.error("Error: " + err));
};
सरलता के लिए, जब भी हमें API से डेटा का अनुरोध करने की आवश्यकता होगी, हम सभी आधुनिक ब्राउज़रों के लिए उपलब्ध Fetch API का उपयोग करेंगे।
एपीआई से बियर की सरणी को पुनः प्राप्त करने के लिए उपरोक्त फ़ंक्शन कुछ कदम उठाता है:
- यह सबसे पहले /index . का अनुरोध करता है एंडपॉइंट एसिंक्रोनस रूप से और
then
जाँचता है कि प्रतिक्रिया स्थिति ठीक के बराबर है या नहीं । - यदि ऐसा होता है, तो हम डेटा को JSON के रूप में वापस कर देते हैं; अन्यथा, एक
Error
फेंक दें । then
, हम अपनी खुद की बियर ऑब्जेक्ट बनाने और राज्य केbeers
में जोड़ने के लिए परिणामों की सरणी पर पुनरावृति करते हैं सरणी।- यदि प्रक्रिया के दौरान कुछ भी गलत हुआ, तो
catch
ब्लॉक अपवाद को कैप्चर करेगा और इसे संदेश अलर्ट के रूप में प्रदर्शित करेगा।
अच्छा है, है ना? यह लगभग वही कदम है जो हम अन्य सभी अनुरोधों के लिए उठाएंगे।
लेकिन, तालिका में डेटा कैसे प्रदर्शित करता है? अच्छा प्रश्न! आइए निम्नलिखित कोड पर एक नज़र डालें:
columns = [
{
title: "Brand",
dataIndex: "brand",
key: "brand",
},
...{
title: "",
key: "action",
render: (_text, record) => (
<Popconfirm title="Are you sure to delete this beer?" onConfirm={() => this.deleteBeer(record.id)} okText="Yes" cancelText="No">
<a href="#" type="danger">
Delete{" "}
</a>
</Popconfirm>
),
},
];
मैंने इसे बेहतर ढंग से समझने के लिए इसे थोड़ा सरल किया है। यह एक सरणी है जो हमारी तालिका के कंकाल का प्रतिनिधित्व करती है। इस प्रकार एएनटीडी टेबल काम करते हैं; उन्हें एक सरणी के रूप में आपकी तालिका संरचना (पंक्तियों और स्तंभों) के बारे में मेटाडेटा जानकारी प्राप्त करने की आवश्यकता है।
प्रत्येक स्तंभ सरणी के भीतर एक वस्तु है, और यहाँ क्रम महत्वपूर्ण है। title
विशेषता कॉलम का नाम प्राप्त करती है, जबकि dataIndex
नाम यह है कि यह कैसे रिएक्ट घटकों के भीतर जाना जाएगा, और key
इसकी विशिष्ट पहचानकर्ता है।
अधिकांश स्तंभों के लिए, क्रियाएँ स्तंभ को छोड़कर, कॉन्फ़िगरेशन समान है। वहां, जब उपयोगकर्ता किसी आइटम को हटाना चाहता है, तो हमें ट्रिगर करने के लिए कार्रवाई का लिंक निर्दिष्ट करना होगा। ध्यान दें कि हम antd के Popconfirm घटक का उपयोग कर रहे हैं।
यह एक बहुत अच्छा घटक है जो उपयोगकर्ताओं को किसी कार्रवाई के होने से पहले पुष्टि करने के लिए प्रेरित करने के काम को सुविधाजनक बनाता है। नीचे दिया गया चित्र दिखाता है कि यह कैसा दिखता है:
हटाने से पहले एक पुष्टिकरण संवाद का संकेत देना।
कार्रवाई हटाएं
किसी आइटम को हटाने के लिए, हमें दो मुख्य ऑपरेशन करने होंगे:एपीआई पर डिलीट कॉल और टेबल रीलोडिंग।
डिलीट फ़ंक्शन हमारे द्वारा किए गए पहले फ़ेच के समान है:
deleteBeer = (id) => {
const url = `api/v1/beers/${id}`;
fetch(url, {
method: "delete",
})
.then((data) => {
if (data.ok) {
this.reloadBeers();
return data.json();
}
throw new Error("Network error.");
})
.catch((err) => message.error("Error: " + err));
};
देखना? यहां केवल एक चीज नई है HTTP method
fetch
. के दूसरे पैरामीटर के रूप में पास किया गया तरीका। साथ ही, then
. के भीतर खंड, हम reloadBeers
. कहते हैं फ़ंक्शन, जो सभी बियर को बैक-एंड से एक बार फिर से लाएगा।
इस फ़ंक्शन की सामग्री काफी हद तक निम्नलिखित है:
reloadBeers = () => {
this.setState({ beers: [] });
this.loadBeers();
};
हम राज्य के beers
. को रीसेट कर रहे हैं सरणी और लोड फ़ंक्शन को फिर से कॉल करना।
अंतिम घटक
अंत में, हमें एंटडी टैग को स्पष्ट रूप से कॉल करके घटक की रचना करने की आवश्यकता है। आइए देखें कि यह अंतिम घटक कोड के साथ कैसे जाता है:
import { Table, message, Popconfirm } from "antd";
import React from "react";
import AddBeerModal from "./AddBeerModal";
class Beers extends React.Component {
columns = [
{
title: "Brand",
dataIndex: "brand",
key: "brand",
},
{
title: "Style",
dataIndex: "style",
key: "style",
},
{
title: "Country",
dataIndex: "country",
key: "country",
},
{
title: "Quantity",
dataIndex: "quantity",
key: "quantity",
},
{
title: "",
key: "action",
render: (_text, record) => (
<Popconfirm title="Are you sure to delete this beer?" onConfirm={() => this.deleteBeer(record.id)} okText="Yes" cancelText="No">
<a href="#" type="danger">
Delete{" "}
</a>
</Popconfirm>
),
},
];
state = {
beers: [],
};
componentDidMount() {
this.loadBeers();
}
loadBeers = () => {
const url = "api/v1/beers/index";
fetch(url)
.then((data) => {
if (data.ok) {
return data.json();
}
throw new Error("Network error.");
})
.then((data) => {
data.forEach((beer) => {
const newEl = {
key: beer.id,
id: beer.id,
brand: beer.brand,
style: beer.style,
country: beer.country,
quantity: beer.quantity,
};
this.setState((prevState) => ({
beers: [...prevState.beers, newEl],
}));
});
})
.catch((err) => message.error("Error: " + err));
};
reloadBeers = () => {
this.setState({ beers: [] });
this.loadBeers();
};
deleteBeer = (id) => {
const url = `api/v1/beers/${id}`;
fetch(url, {
method: "delete",
})
.then((data) => {
if (data.ok) {
this.reloadBeers();
return data.json();
}
throw new Error("Network error.");
})
.catch((err) => message.error("Error: " + err));
};
render() {
return (
<>
<Table className="table-striped-rows" dataSource={this.state.beers} columns={this.columns} pagination={{ pageSize: 5 }} />
<AddBeerModal reloadBeers={this.reloadBeers} />
</>
);
}
}
export default Beers;
अब, आप सब कुछ एक साथ देख सकते हैं। रेंडर फ़ंक्शन हमारे द्वारा वहां आयात किए जा रहे दो टैग प्रदर्शित करेगा:antd का Table
घटक और AddBeerModal
(मोडल फॉर्म हम कुछ ही मिनटों में बनाएंगे)।
तालिका घटक इस तरह से बहुत समृद्ध है कि यह हमें pagination
सेट करके परिणामों के माध्यम से स्वचालित रूप से पृष्ठांकित करने की अनुमति देता है वस्तु। केवल एक ही संपत्ति जो हम यहां जोड़ रहे हैं वह है प्रत्येक पृष्ठ का आकार (प्रति पृष्ठ 5 परिणाम)।
dataSource
विशेषता उन बियर की सूची प्राप्त करती है जिन्हें हमने बैक-एंड से माउंट किया है, और columns
विशेषता हमारे द्वारा पहले से निर्मित मेटाडेटा प्राप्त करती है।
AddBeerModal घटक
तालिका के नीचे, आप नई बियर जोड़ने के लिए एक बटन देख सकते हैं। जब हम इस बटन पर क्लिक करते हैं, तो यह हमारे कैटलॉग में नई बियर को पंजीकृत करने के लिए एक फॉर्म के साथ एक मोडल खोलेगा, जैसा कि आप नीचे देख सकते हैं:
कैटेलॉग में नई बियर जोड़ना।
यह पता लगाने का एक शानदार तरीका है कि antd रूपों को भी कैसे संभालता है।
सबसे पहले, आइए इस घटक में हमारे द्वारा किए जाने वाले कार्यों को तोड़ दें। ध्यान दें कि घटक स्वयं दो से बना है:एक बटन और एक मॉडल।
इसका मतलब है कि हमें इन दोनों से संबंधित कार्यों को मैप करना होगा:
showModal
औरhandleCancel
मोडल के खुलने और बंद होने से निपटें।onFinish
जब हम फॉर्म जमा करते हैं तो ट्रिगर होता है।
वे घटक की स्थिति के साथ खेलेंगे, जो केवल मोडल टॉगल को संग्रहीत करेगा (यानी, क्या यह दृश्यमान है):
state = {
visible: false,
};
मोडल को दिखाने या छिपाने के लिए, हमें बस इस बूलियन को टॉगल करना होगा:
this.setState({
visible: true,
});
बीयर के एपीआई को कॉल करने और एक नई बीयर रजिस्टर करने के लिए, हमें फिर से फ़ेच एपीआई का इस्तेमाल करना होगा:
onFinish = (values) => {
const url = "api/v1/beers/";
fetch(url, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(values),
})
.then((data) => {
if (data.ok) {
this.handleCancel();
return data.json();
}
throw new Error("Network error.");
})
.then(() => {
this.props.reloadBeers();
})
.catch((err) => console.error("Error: " + err));
};
यह पहली बार है जब हम एक अनुरोध कॉल कर रहे हैं जिसमें हम सर्वर को डेटा भेजते हैं। इस मामले में, हमें एपीआई को स्पष्ट रूप से यह भी बताना होगा कि किस प्रकार की जानकारी आगे बढ़ रही है। इसीलिए headers
विशेषता को सूचित किया जाना चाहिए।
अगर सब कुछ ठीक हो जाता है, तो हम बस मोडल को बंद कर देते हैं और टेबल की लिस्टिंग को फिर से लोड करते हैं।
अब, घटक रेंडर के साथ सब कुछ एक साथ देखते हैं:
import { Button, Form, Input, Modal, Select } from "antd";
import React from "react";
const { Option } = Select;
class AddBeerModal extends React.Component {
formRef = React.createRef();
state = {
visible: false,
};
onFinish = (values) => {
const url = "api/v1/beers/";
fetch(url, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(values),
})
.then((data) => {
if (data.ok) {
this.handleCancel();
return data.json();
}
throw new Error("Network error.");
})
.then(() => {
this.props.reloadBeers();
})
.catch((err) => console.error("Error: " + err));
};
showModal = () => {
this.setState({
visible: true,
});
};
handleCancel = () => {
this.setState({
visible: false,
});
};
render() {
return (
<>
<Button type="primary" onClick={this.showModal}>
Create New +
</Button>
<Modal title="Add New Beer ..." visible={this.state.visible} onCancel={this.handleCancel} footer={null}>
<Form ref={this.formRef} layout="vertical" onFinish={this.onFinish}>
<Form.Item name="brand" label="Brand" rules={[{ required: true, message: "Please input your beer brand!" }]}>
<Input placeholder="Input your beer brand" />
</Form.Item>
<Form.Item name="style" label="Style" rules={[{ required: true, message: "Please input your beer style!" }]}>
<Input placeholder="Input your beer style" />
</Form.Item>
<Form.Item
name="country"
label="Country"
rules={[
{
required: true,
message: "Please input the country of the beer!",
},
]}
>
<Select showSearch placeholder="Select your beer country" optionFilterProp="children" style={{ width: "100%" }}>
<Option value="Finland">Finland</Option>
<Option value="Germany">Germany</Option>
<Option value="Netherlands">Netherlands</Option>
<Option value="UK">UK</Option>
<Option value="USA">USA</Option>
<Option value="Other">Other</Option>
</Select>
</Form.Item>
<Form.Item name="quantity" label="Quantity" rules={[{ required: true, message: "Please input the quantity!" }]}>
<Input type="number" placeholder="How many beers you desire?" />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
</Modal>
</>
);
}
}
export default AddBeerModal;
Antd allows us to specify each form’s item rules individually. If a field is required, just say so by providing a rules
attribute. You can customize the message it’ll display in case the user submits the form without filling it properly:
Validating form inputs.
Take a look at the Select
component, which translates a combo box. See how easy it is to create complex components by just providing the right attributes. For example, if you want to make your select searchable, just put the showSearch
property, there and it’s done:
Filtering results within a Select.
Antd will automatically filter the select options based on your input.
Styling
Sometimes, you’ll need to provide some CSS styling to components that do not provide a default (like antd’s table) or customize the ones that come built-in.
To do this, you can create as many CSS files as you want and organize them in a structure that pleases you. Rails already create an application.css file, under the app/assets/stylesheets फ़ोल्डर। Open it and the following content:
.site-layout-content {
background: #fff;
padding: 24px;
min-height: 380px;
}
.logo {
width: 200px;
min-height: 31px;
margin: 16px 24px 16px 0;
float: left;
background-image: url(https://www.honeybadger.io/images/navbar_logo.svg?1602785015);
background-repeat: no-repeat;
}
.table-striped-rows th,
.table-striped-rows td {
border-bottom: 1px solid #dedddd !important;
}
.table-striped-rows tr:nth-child(2n) td {
background-color: #fbfbfb;
}
.table-striped-rows thead {
background-color: #f1f1f1;
}
Those are the CSS rules to make our table stripped, for example. Feel free to add as many extra styles here as you want.
परीक्षण
Before heading to the tests, we need to disable the CSRF token checking that Rails automatically configures for our apps. To do so, go to the app/controllers/application_controller.rb file and change it to the following:
class ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
end
This way, we avoid having to validate the tokens each time we perform a request.
Great! Now, start your server via rails s
command, access the https://localhost:3000/ address, and play around with the CRUD.
निष्कर्ष
As a homework task, I’d recommend that you try implementing the update functionality of the CRUD. You can adapt the edit
method at the API controller to receive the updated beer info and perform the update to the database. For the view, another modal would suit very well to accommodate the edit’s form.
You can also find the source code for this tutorial here. Good studies!