State Hoisting বোঝার সহজ উপায় - Jetpack Compose এ

 

State Hoisting বোঝার সহজ উপায় - Jetpack Compose এ

আমরা Jetpack Compose-এ State Hoisting কোথায় করবো, সেটা বুঝতে হলে প্রথমে কিছু গুরুত্বপূর্ণ ধারণা পরিষ্কার করা দরকার।


📌 State Hoisting কী?

Jetpack Compose-এ State Hoisting বলতে বোঝায়, UI state (অর্থাৎ, UI সম্পর্কিত ডাটা) নিচের কোন কম্পোনেন্টে না রেখে উপরের কোন কম্পোনেন্টে নিয়ে আসা, যাতে একাধিক কম্পোনেন্ট সেই state ব্যবহার করতে পারে।

এটা "Single Source of Truth" (SSOT) মেনে চলে, যেখানে state এক জায়গায় রাখা হয় এবং সেটি নিচের কম্পোনেন্টগুলোতে পাস করা হয়।


🤔 State কোথায় রাখা উচিত?

  • ছোট ও নির্দিষ্ট কম্পোনেন্টের জন্য 👉 ভিতরের (internal) state রাখা ভালো।
  • একাধিক কম্পোনেন্টের জন্য 👉 State Hoisting করে উপরের কম্পোনেন্টে রাখা ভালো।
  • বিজনেস লজিক যুক্ত থাকলে 👉 ViewModel-এ state রাখা উচিত।

🎯 কখন State Hoisting করবো?

✅ যখন...

একাধিক কম্পোনেন্ট একই state ব্যবহার করবে।
State পরিবর্তন করার লজিক উপরের কোন কম্পোনেন্টে রাখতে হবে।
State সংরক্ষণ করা দরকার (যেমন: স্ক্রল পজিশন, ফর্ম ডাটা ইত্যাদি)।

❌ যখন নয়...

❌ যদি state শুধু একটি নির্দিষ্ট কম্পোনেন্টেই দরকার হয়
❌ যদি State Hoisting করলে কোড অপ্রয়োজনীয় জটিল হয়ে যায়।


🛠️ উদাহরণ: State Hoisting করা উচিত নাকি নয়?

🚀 ১️⃣ যখন State Hoisting করা দরকার নয়

@Composable
fun ChatBubble(message: String) {
    var isExpanded by rememberSaveable { mutableStateOf(false) }  // Internal state

    Column(modifier = Modifier.clickable { isExpanded = !isExpanded }) {
        Text(text = message)
        if (isExpanded) {
            Text(text = "Timestamp: 10:00 AM")
        }
    }
}

🔹 ব্যাখ্যা:
👉 এখানে isExpanded state শুধু ChatBubble কম্পোনেন্টের মধ্যেই প্রয়োজন, তাই এটি ভিতরে রাখাই ভালো


🚀 ২️⃣ যখন State Hoisting করা দরকার

@Composable
fun ConversationScreen() {
    var selectedMessage by remember { mutableStateOf<String?>(null) }  // Hoisted State

    Column {
        MessageList(messages, onMessageClick = { selectedMessage = it })
        if (selectedMessage != null) {
            MessageDetails(message = selectedMessage!!)
        }
    }
}

@Composable
fun MessageList(messages: List<String>, onMessageClick: (String) -> Unit) {
    Column {
        messages.forEach { message ->
            Text(
                text = message,
                modifier = Modifier.clickable { onMessageClick(message) }
            )
        }
    }
}

🔹 ব্যাখ্যা:
👉 এখানে selectedMessage state উপরের ConversationScreen কম্পোনেন্টে রাখা হয়েছে, কারণ এটি MessageList ও MessageDetails কম্পোনেন্টের মধ্যে শেয়ার করা হবে


💡 ViewModel ব্যবহার করে State Hoisting

যখন state-এর মধ্যে বিজনেস লজিক থাকে, তখন আমরা এটি ViewModel এ রাখি।

class ConversationViewModel : ViewModel() {
    private val _messages = MutableStateFlow<List<String>>(emptyList())
    val messages: StateFlow<List<String>> = _messages

    fun sendMessage(message: String) {
        _messages.value = _messages.value + message
    }
}

@Composable
fun ConversationScreen(viewModel: ConversationViewModel = viewModel()) {
    val messages by viewModel.messages.collectAsState()

    Column {
        MessageList(messages)
        Button(onClick = { viewModel.sendMessage("New Message") }) {
            Text("Send")
        }
    }
}

🔹 ব্যাখ্যা:
👉 State (messages) এখন ViewModel-এ রাখা হয়েছে, যা Activity/Fragment-এর lifecycle অনুযায়ী বাঁচবে।
👉 UI ViewModel থেকে ডাটা নেয়, এবং ViewModel-এর ফাংশন (sendMessage) দিয়ে ডাটা আপডেট হয়।


💎 সারাংশ

1️⃣ State শুধু একটি কম্পোনেন্টের জন্য হলে 👉 কম্পোনেন্টের মধ্যেই রাখো।
2️⃣ একাধিক কম্পোনেন্টে শেয়ার করতে হলে 👉 Hoisting করো (উপরে নিয়ে আসো)।
3️⃣ বিজনেস লজিক থাকলে 👉 ViewModel-এ রাখো।
4️⃣ "Single Source of Truth" মেনে state পরিচালনা করো।

এতে কোড ক্লিন, মেইনটেইনেবল ও স্কেলেবল হবে! 🚀

Comments

Popular posts from this blog

AI (Artificial Intelligence) সহজভাবে বোঝার জন্য একদম মস্তিষ্ক-বান্ধব ব্যাখ্যা 🧠🤖

🧠 Regex কী?

Kotlin-এ ভেরিয়েবল ঘোষণা করার দুই উপায়