পাঠ ২৩ · ৫৭-এর মধ্যে · মডিউল ৫
Home / Courses / Mobile App Development / কাস্টম কম্পোনেন্ট

কাস্টম কম্পোনেন্ট ও পুনঃব্যবহারযোগ্যতা

Custom components & reusability
৭ মিনিট পড়া মধ্যম · Intermediate Python কোডসহ সম্পূর্ণ বাংলায়

এই পাঠে যা শিখবেন

  • ছোট উইজেট থেকে বড়, পুনঃব্যবহারযোগ্য কাস্টম কম্পোনেন্ট বানানোর ধারণা
  • একটি কাস্টম কম্পোনেন্ট আসলে "প্যারামিটারাইজড উইজেট-সাবট্রি তৈরি করা একটি ফাংশন" — এর বেশি কিছু নয়
  • Python দিয়ে একটি Card কম্পোনেন্ট তৈরি ও তিনবার ভিন্ন ডেটায় ইনস্ট্যান্স করা
  • একই কম্পোনেন্ট সংজ্ঞা কীভাবে ভিন্ন ভিন্ন প্রকৃত আউটপুট তৈরি করে তা রেন্ডার-আউটপুট দিয়ে যাচাই

১ · কাস্টম কম্পোনেন্ট মানে কী

L20-এ আমরা দেখেছিলাম Text, Input, Button-এর মতো ছোট, বিল্ট-ইন-স্টাইল উইজেট ফাংশন কম্পোজ করে একটি স্ক্রিন বানানো যায়। কিন্তু একই প্যাটার্নের উইজেট-গ্রুপ যদি অ্যাপের বিভিন্ন জায়গায় বারবার দরকার হয় (যেমন একটি "প্রোডাক্ট কার্ড" — একটি শিরোনাম + একটি সাবটাইটেল, একটি বক্সে মোড়ানো), তাহলে প্রতিবার হাতে সেই একই গঠন লেখা অপচয় ও ভুলের ঝুঁকিপূর্ণ। এখানেই কাস্টম কম্পোনেন্টCustom Componentছোট উইজেট কম্পোজ করে বানানো একটি প্যারামিটারাইজড ফাংশন, যা কল হলে একটি সম্পূর্ণ উইজেট-সাবট্রি রিটার্ন করে -- বারবার ভিন্ন ডেটা দিয়ে পুনঃব্যবহারযোগ্য। কাজে লাগে — এটি আসলে শুধু একটি ফাংশন, যা প্যারামিটার নেয় ও L20-এর একই {"type", "props", "children"} শেপে একটি উইজেট-সাবট্রি রিটার্ন করে।

প্যারামিটারাইজেশন
কাস্টম কম্পোনেন্ট প্যারামিটার নেয় (title, subtitle, onPress) — একই সংজ্ঞা, ভিন্ন ইনপুট, ভিন্ন আউটপুট।
পুনঃব্যবহারযোগ্যতা
একবার সংজ্ঞায়িত হলে অ্যাপের যেকোনো স্ক্রিনে যতবার প্রয়োজন ইনস্ট্যান্স করা যায় — কোড ডুপ্লিকেশন ছাড়াই।
কম্পোজিশন-ওভার-ডুপ্লিকেশন
বড় কম্পোনেন্ট ছোট কম্পোনেন্ট দিয়ে গঠিত হতে পারে — কাস্টম কম্পোনেন্টও নিজেই আরেকটি বড় কাস্টম কম্পোনেন্টের চাইল্ড হতে পারে।

২ · একটি Card কম্পোনেন্ট বানানো ও তিনবার ব্যবহার করা

নিচের কোড সেলে আমরা L20-এর মতোই কয়েকটি বেসিক উইজেট ফাংশন সংজ্ঞায়িত করব, তারপর সেগুলো দিয়ে একটি Card(title, subtitle) কাস্টম কম্পোনেন্ট বানাব। এই একই Card ফাংশনকে তিনবার ভিন্ন ভিন্ন ডেটা দিয়ে কল করে তিনটি ভিন্ন কার্ড-ইনস্ট্যান্স তৈরি করব, তারপর একটি রিকার্সিভ render ফাংশন দিয়ে তিনটিই প্রকৃত "draw operation" লিস্টে রূপান্তর করে দেখাব — প্রমাণ করব একই কম্পোনেন্ট সংজ্ঞা সত্যিই ভিন্ন কনক্রিট আউটপুট তৈরি করছে।

Python
# বেসিক উইজেট ফাংশন (L20-এর একই শেপ) + একটি কাস্টম Card কম্পোনেন্ট

def Text(content):
    return {"type": "Text", "props": {"content": content}, "children": []}

def Container(*children, direction="column"):
    return {"type": "Container", "props": {"direction": direction}, "children": list(children)}


def Card(title, subtitle):
    """কাস্টম কম্পোনেন্ট -- ছোট উইজেট কম্পোজ করে একটি সম্পূর্ণ উইজেট-সাবট্রি রিটার্ন করে।
    title/subtitle প্যারামিটারের ভিত্তিতে ভিন্ন ভিন্ন কনক্রিট আউটপুট তৈরি হয়।"""
    return {
        "type": "Card",
        "props": {"title": title, "subtitle": subtitle},
        "children": [
            Text(title),
            Text(subtitle),
        ],
    }


# একই Card() সংজ্ঞা -- তিনবার ভিন্ন ভিন্ন ডেটা দিয়ে ইনস্ট্যান্স করা
card1 = Card("প্রোডাক্ট: হেডফোন", "মূল্য: ১,২০০ টাকা")
card2 = Card("প্রোডাক্ট: কীবোর্ড", "মূল্য: ২,৫০০ টাকা")
card3 = Card("প্রোডাক্ট: মাউস", "মূল্য: ৬০০ টাকা")

cards = [card1, card2, card3]


def render(widget, x=0, y=0):
    """রিকার্সিভভাবে ট্রি ওয়াক করে প্রকৃত draw-operation লিস্ট তৈরি করে (L20-এর print_tree-এর মতো ধারণা,
    কিন্তু এখানে সরাসরি ড্র-অপারেশন ট্যুপল রিটার্ন করে)"""
    ops = []
    row_height = 22

    if widget["type"] == "Card":
        card_height = row_height * len(widget["children"]) + 12
        ops.append(("draw_rect", x, y, 220, card_height))
        inner_y = y + 8
        for child in widget["children"]:
            ops.extend(render(child, x + 12, inner_y))
            inner_y += row_height
    elif widget["type"] == "Text":
        ops.append(("draw_text", x, y, widget["props"]["content"]))

    return ops


print("=== তিনটি ভিন্ন Card ইনস্ট্যান্স রেন্ডার করা হচ্ছে ===\n")
cursor_y = 0
for i, card in enumerate(cards, start=1):
    ops = render(card, x=0, y=cursor_y)
    print(f"-- Card ইনস্ট্যান্স #{i} --")
    for op in ops:
        print(f"  {op}")
    cursor_y += 90

print(f"\nমোট ইনস্ট্যান্স সংখ্যা: {len(cards)}")
print(f"প্রতিটি ইনস্ট্যান্সের title আলাদা: {[c['props']['title'] for c in cards]}")

    
লক্ষ্য করুন Card ফাংশনের সংজ্ঞা মাত্র একবার লেখা হয়েছে, কিন্তু card1, card2, card3 — প্রতিটির props["title"], props["subtitle"] এবং render()-এর আউটপুটে থাকা প্রকৃত draw_text কন্টেন্ট আলাদা। এটিই পুনঃব্যবহারযোগ্যতার মূল সুবিধা — একটি সংজ্ঞা, একাধিক স্বতন্ত্র ব্যবহার, প্রতিটি নিজের ডেটা অনুযায়ী সঠিক আউটপুট তৈরি করে, কোনো কোড কপি-পেস্ট ছাড়াই।
মূল কথা · Key takeaway

একটি কাস্টম কম্পোনেন্ট আসলে জাদুকরী কিছু নয় — এটি শুধু একটি ফাংশন যা প্যারামিটার নেয় এবং ছোট উইজেট কম্পোজ করে একটি উইজেট-সাবট্রি রিটার্ন করে (L20-এর একই শেপ অনুসরণ করে)। এই একই সংজ্ঞা বারবার, ভিন্ন ভিন্ন ডেটা দিয়ে ইনস্ট্যান্স করা যায় — এটিই কেন React/Flutter/SwiftUI-স্টাইল ফ্রেমওয়ার্কে বড় অ্যাপও শেষ পর্যন্ত মুষ্টিমেয় কিছু পুনঃব্যবহারযোগ্য কম্পোনেন্টের সমন্বয়ে গঠিত হতে পারে।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।

প্র ০১ উপরের কোড সেলে card1, card2, card3 — এই তিনটি ডিকশনারির "type" ভ্যালু কি একই না ভিন্ন?

একই — তিনটিরই "type" হলো "Card", কারণ তিনটিই একই Card() ফাংশন কল করে তৈরি হয়েছে। যা ভিন্ন তা হলো "props"-এর ভেতরের মান (title, subtitle) এবং সেই কারণে children-এর ভেতরের Text নোডগুলোর কন্টেন্ট — গঠন (structure) একই, ডেটা ভিন্ন।

প্র ০২ যদি Card-এ একটি তৃতীয় প্যারামিটার on_press (একটি ফাংশন) যোগ করা হয়, এটি কি পুনঃব্যবহারযোগ্যতা নীতির সাথে সামঞ্জস্যপূর্ণ হবে?

হ্যাঁ — এটিই ঠিক এই নীতির শক্তি। প্রতিটি Card ইনস্ট্যান্স তার নিজস্ব on_press ফাংশন দিতে পারবে (যেমন card1 একটি প্রোডাক্ট পেজে নিয়ে যাবে, card2 অন্য একটিতে), অথচ Card-এর মূল সংজ্ঞা (গঠন, লেআউট) একটাই থাকবে — একই কম্পোনেন্ট, ভিন্ন আচরণ, শুধু প্যারামিটারের মাধ্যমে।

প্র ০৩ render() ফাংশনটি কি Card সম্পর্কে "জানে" যে এটি তিনবার ভিন্ন ডেটায় ব্যবহৃত হচ্ছে?

না — render()-এর কোনো ধারণাই নেই যে এটি কতবার বা কোন কোন ডেটায় কল হয়েছে। এটি শুধু একটি নির্দিষ্ট উইজেট-ডিকশনারি (যা তাকে পাস করা হয়েছে) ওয়াক করে draw-অপারেশন তৈরি করে। "তিনবার ভিন্ন ইনস্ট্যান্স" ধারণাটি সম্পূর্ণভাবে কল করার পক্ষ থেকে (for card in cards লুপ) আসে, নিজে render()-এর ভেতরে নয় — এটিই দেখায় কেন কম্পোনেন্ট ও তার রেন্ডারিং লজিক আলাদা রাখা ভালো।

অনুশীলন

  1. চিন্তা করুন: আপনার পরিচিত কোনো অ্যাপে এমন একটি UI প্যাটার্ন খুঁজে বের করুন যা স্ক্রিন জুড়ে বারবার দেখা যায় (যেমন একটি নোটিফিকেশন আইটেম, একটি চ্যাট বাবল, একটি প্রোডাক্ট থাম্বনেইল) — এটিকে কী প্যারামিটার নিয়ে একটি কাস্টম কম্পোনেন্ট হিসেবে ডিজাইন করবেন?

    একটি চ্যাট বাবল কম্পোনেন্টের জন্য যুক্তিসঙ্গত প্যারামিটার হতে পারে message_text, is_sent_by_me (বাবলের রং/অ্যালাইনমেন্ট নির্ধারণ করতে), ও timestamp — একই ChatBubble() ফাংশন কনভারসেশনের প্রতিটি মেসেজের জন্য একবার করে কল হবে, প্রতিবার ভিন্ন ডেটা দিয়ে, ঠিক এই পাঠের Card-এর মতোই।

  2. পরীক্ষা করুন: উপরের কোড সেলে একটি চতুর্থ কার্ড যোগ করুন — card4 = Card("প্রোডাক্ট: চার্জার", "মূল্য: ৩৫০ টাকা") — এবং সেটি cards লিস্টে যোগ করুন, তারপর কোড আবার চালিয়ে দেখুন লুপ স্বয়ংক্রিয়ভাবে চতুর্থ কার্ডটিও রেন্ডার করে কি না।

    হ্যাঁ — for i, card in enumerate(cards, start=1) লুপটি cards লিস্টের দৈর্ঘ্যের উপর নির্ভরশীল, নির্দিষ্ট সংখ্যার উপর নয়। তাই card4 যোগ করলে আউটপুটে "-- Card ইনস্ট্যান্স #4 --" স্বয়ংক্রিয়ভাবে দেখা যাবে, এবং "মোট ইনস্ট্যান্স সংখ্যা" ৩ থেকে বেড়ে ৪ হবে — কোনো নতুন রেন্ডারিং কোড না লিখেই, কারণ Card ও render() উভয়ই সাধারণীকৃত (generalized)।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

  • কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ অ্যাপ লাইফসাইকেল, মোবাইল UI/UX, MVVM/MVI আর্কিটেকচার, নেটিভ বনাম ক্রস-প্ল্যাটফর্ম, নেভিগেশন, স্টেট ম্যানেজমেন্ট, লোকাল স্টোরেজ, ডিভাইস ফিচার ও ডিপ্লয়মেন্ট — বাকি পাঠগুলো শীঘ্রই যুক্ত হবে।
  • Full-Stack Web Frameworks কোর্স সহোদর কোর্স ওয়েব কম্পোনেন্ট ফ্রেমওয়ার্কেও (React, Vue) একই "প্যারামিটারাইজড ফাংশন কম্পোজিশন" নীতি প্রয়োগ হয় — শুধু প্ল্যাটফর্ম-নির্দিষ্ট সিনট্যাক্স আলাদা।
  • সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture, Programming Languages & Compiler Design, Software Engineering & Git, Theory of Computation, Engineering Economics, Full-Stack Web Frameworks ও Mobile App Development — সব এক জায়গায়।
আগের পাঠ
লেআউট ইঞ্জিন — কনস্ট্রেইন্ট ও ফ্লেক্সবক্স-স্টাইল সিস্টেম