State ডিফল্টভাবে একটি কম্পোনেন্টের ভেতরে থাকে, বাকি প্রতিটি কম্পোনেন্টের কাছে অদৃশ্য — এমনকি নিজের সিবলিংদের কাছেও। দুটো কম্পোনেন্টের একই state শেয়ার বা সমন্বয় করার দরকার হলে, প্রচলিত সমাধান হলো state উপরে তোলা: এটাকে তাদের নিকটতম সাধারণ parent-এ সরানো।
দুটো সিবলিং কম্পোনেন্ট, প্রতিটির নিজস্ব আলাদা state, একে অপরকে একদমই দেখতে বা প্রভাবিত করতে পারে না:
function TemperatureInput() {
const [value, setValue] = useState('');
return <input value={value} onChange={(e) => setValue(e.target.value)} />;
}
function App() {
return (
<div>
<TemperatureInput />
<TemperatureInput /> {/* Completely separate state — they can't stay in sync */}
</div>
);
}useState কলটি App-এ তুলুন, আর মান আর সেটা বদলানোর একটি উপায় দুটোই props হিসেবে নিচে পাস করুন:
function TemperatureInput({ value, onChange }) {
return <input value={value} onChange={(e) => onChange(e.target.value)} />;
}
function App() {
const [temperature, setTemperature] = useState('');
return (
<div>
<TemperatureInput value={temperature} onChange={setTemperature} />
<p>Current: {temperature}</p> {/* Now this can see it too */}
</div>
);
}TemperatureInput আর একদমই কোনো state ধরে রাখে না — এটা শুধু যে value দেওয়া হয়েছে তা দেখায়, আর onChange-এর মাধ্যমে উপরে পরিবর্তন জানায়। এরকম একটি কম্পোনেন্ট, নিজের কোনো state ছাড়া, প্রায়ই একটি controlled component বলা হয় — আগের Forms পাঠের একটি controlled form input-এর একই ধারণা, যেকোনো কম্পোনেন্টে সাধারণীকৃত।
একটি React ট্রি জুড়ে ডেটা কীভাবে চলে তার এটাই সাধারণ আকৃতি, আর এটা স্পষ্টভাবে নাম দেওয়ার মতো: ডেটা নিচে যায় props-এর মাধ্যমে, আর পরিবর্তন উপরে আসে props হিসেবে পাস করা callback ফাংশনের মাধ্যমে। একটি child-এর সরাসরি উপরে পৌঁছে একটি parent-এর state বদলানোর কোনো বিল্ট-ইন উপায় React-এ ইচ্ছাকৃতভাবে নেই — এই এক-মুখী প্রবাহই একটি বড় কম্পোনেন্ট ট্রির আচরণকে ট্রেসযোগ্য রাখে।
যখন state উপরে তোলা যথেষ্ট নয়
এই অংশের পরের Context API পাঠে state শেয়ার করার অন্য টুল দেখানো হবে — নির্দিষ্টভাবে দরকারি যখন state উপরে তোলার মানে হবে অনেকগুলো কম্পোনেন্ট স্তর জুড়ে props পাস করা যাদের অন্যথায় এটার দরকারই নেই।