ReactJS State & useState Hook ඉගෙන ගනිමු | Sinhala Tutorial

ReactJS State & useState Hook ඉගෙන ගනිමු | Sinhala Tutorial

කොහොමද යාලුවනේ! ReactJS State සහ useState Hook එකේ බලය අත්විඳිමු!

ReactJS කියන්නේ අද වෙද්දි Web Application Development ලෝකයේ ඉහළින්ම තියෙන එක Framework එකක්. Dynamic User Interfaces (UI) නිර්මාණය කරන්න මේක ගොඩක් ප්‍රයෝජනවත් වෙනවා. ඒත් මේ dynamic ස්වභාවය පවතින්නේ කොහොමද? 🤔 ඒකට ප්‍රධානම හේතුවක් තමයි State කියන concept එක. අද අපි මේ React State එකයි, නවීන React Functional Components වලට State එක ගේන්න උදව් වෙන useState Hook එකයි ගැන ගැඹුරින් කතා කරමු.

මේ ලිපිය කියවීමෙන් පස්සේ ඔයාට React State එක හරියටම තේරුම් ගන්නත්, useState Hook එක ප්‍රායෝගිකව භාවිතා කරන්නත්, ඒකෙන් වෙන්න පුළුවන් වැරදි මඟහරව ගන්නත් පුළුවන් වේවි. එහෙනම් වැඩේට බහිමුද?

State යනු කුමක්ද? (What is State?)

සරලව කිව්වොත්, State කියන්නේ React Component එකක් ඇතුළත ඕනෑම වෙලාවක වෙනස් වෙන්න පුළුවන්, ඒ වගේම UI එකට බලපාන data එකක්. Component එකේ 'memory' එක වගේ තමයි මේක වැඩ කරන්නේ.

උදාහරණයක් විදියට හිතන්න: ෆේස්බුක් එකේ Like button එකක්. ඔයා Like එකක් දැම්මම ඒකේ තියෙන Like ගාන වැඩි වෙනවා, ඒ වගේම button එකේ පාට වෙනස් වෙනවා. මේ 'Like ගාන' සහ 'button එකේ තත්ත්වය' (ලයික් කරලාද, නැද්ද) කියන්නේ ඒ component එකේ State එක. මේ State එක වෙනස් වෙනකොට React automatically UI එක update කරනවා.

Components වලට State අවශ්‍ය ඇයි? (Why do Components Need State?)

Components වලට State අවශ්‍ය වෙන්නේ ප්‍රධාන වශයෙන් මේ හේතු නිසා:

  • Dynamic Data Handling: User input, API calls වලින් එන data, timer values වගේ දේවල් manage කරන්න.
  • Interactive UIs: Buttons වලට click කරන්න, forms වල data submit කරන්න, Tabs මාරු කරන්න වගේ user interactions වලට ප්‍රතිචාර දක්වන්න.
  • Component-specific Data: එක් එක් component එකට ආවේණික තොරතුරු තියාගන්න.

අපි මේ State එක නැතුව වැඩ කළොත්, අපිට පුළුවන් වෙන්නේ Static Web Pages විතරයි හදන්න. ඒ කියන්නේ, Facebook, YouTube, Instagram වගේ Interactive Websites හදන්න බෑ.

useState Hook එක හඳුනාගනිමු (Introducing the useState Hook)

පරණ React Versions වලදී State manage කරන්න Class Components තමයි භාවිතා කළේ. ඒත් React 16.8 වලින් පස්සේ ආපු Hooks කියන concept එකත් එක්ක, Functional Components වලටත් State manage කරන්න පුළුවන් වුණා. මේ අතරින් State manage කරන්න අපි ප්‍රධාන වශයෙන්ම භාවිතා කරන්නේ useState Hook එක.

useState කියන්නේ React වලින් අපිට දෙන special function එකක්. මේකෙන් අපිට Functional Component එකක් ඇතුළේ State variable එකක් declare කරන්න පුළුවන්. ඒක භාවිතා කරන විදිය මෙහෙමයි:


import React, { useState } from 'react';

function MyComponent() {
  const [count, setCount] = useState(0); // Here's the useState Hook!

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

export default MyComponent;

මේ Code එකේ තියෙන කොටස් ගැන ටිකක් පැහැදිලි කරමු:

  • import React, { useState } from 'react';: අපි මුලින්ම useState Hook එක React library එකෙන් import කරගන්න ඕන.
  • const [count, setCount] = useState(0);:
    • useState(0): මේක තමයි Hook එක. මේකේ bracket ඇතුළට අපි දෙන 0 කියන්නේ count කියන State variable එකේ initial value එක. ඒ කියන්නේ component එක මුලින්ම render වෙනකොට count එකේ අගය 0 වෙනවා.
    • [count, setCount]: useState Hook එක අපිට array එකක් විදියට values දෙකක් return කරනවා:
      • count: මේක තමයි අපේ State variable එක. මේකේ තමයි අපේ current State value එක තියෙන්නේ.
      • setCount: මේක තමයි setter function එක. අපිට count එකේ අගය වෙනස් කරන්න අවශ්‍ය නම්, අපි මේ function එක භාවිතා කරන්න ඕන. කිසිම වෙලාවක count = 5 වගේ කෙලින්ම State variable එකේ අගය වෙනස් කරන්න එපා!

setCount වගේ setter function එකක් call කළාම React auto-magically component එක re-render කරලා UI එක update කරනවා. මේක තමයි State Management වල තියෙන සුන්දරත්වය.

ප්‍රායෝගික උදාහරණ (Practical Examples)

දැන් අපි බලමු useState Hook එක භාවිතා කරලා පොඩි Web Applications දෙකක් හදන්නේ කොහොමද කියලා.

Simple Counter Application

අපි මුලින්ම 'Increment' සහ 'Decrement' බොත්තම් දෙකක් තියෙන, Click කරනකොට අගය වැඩි වෙන හෝ අඩු වෙන Counter එකක් හදමු. මෙය React State immutability ගැන අවබෝධයක් ලබා ගැනීමට හොඳ උදාහරණයකි.


import React, { useState } from 'react';

function Counter() {
  // count කියන State variable එකයි, setCount කියන setter function එකයි create කරගමු.
  // මුලික අගය 0.
  const [count, setCount] = useState(0);

  // count එක වැඩි කරන function එක.
  const increment = () => {
    // setCount function එකට current count එකට 1ක් එකතු කරලා දෙනවා.
    // React මේක detect කරලා component එක re-render කරනවා.
    setCount(count + 1);
  };

  // count එක අඩු කරන function එක.
  const decrement = () => {
    // setCount function එකට current count එකෙන් 1ක් අඩු කරලා දෙනවා.
    setCount(count - 1);
  };

  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h2>Simple Counter Application</h2>
      <p style={{ fontSize: '48px', margin: '20px 0' }}>{count}</p>
      <button
        onClick={increment}
        style={{
          padding: '10px 20px',
          fontSize: '20px',
          margin: '0 10px',
          backgroundColor: '#4CAF50',
          color: 'white',
          border: 'none',
          borderRadius: '5px',
          cursor: 'pointer',
        }}
      >
        Increment
      </button>
      <button
        onClick={decrement}
        style={{
          padding: '10px 20px',
          fontSize: '20px',
          margin: '0 10px',
          backgroundColor: '#f44336',
          color: 'white',
          border: 'none',
          borderRadius: '5px',
          cursor: 'pointer',
        }}
      >
        Decrement
      </button>
    </div>
  );
}

export default Counter;

මේ code එක බලන්න. count කියන State එක වෙනස් කරන්න අපි හැමවිටම setCount කියන setter function එක භාවිතා කළා. මේක immutability කියන concept එකට ගොඩක් වැදගත්. ඒ කියන්නේ State එක කෙලින්ම modify කරන්නේ නැතුව, අලුත් State එකක් create කරලා ඒක setter function එකට දෙන එක.

Toggle Component (Show/Hide Text)

දැන් අපි බලමු 'Show/Hide' බොත්තමක් භාවිතා කරලා Text එකක් Toggle කරන්නේ කොහොමද කියලා. මේකට අපිට Boolean State එකක් අවශ්‍ය වෙනවා.


import React, { useState } from 'react';

function ToggleText() {
  // isVisible කියන Boolean State variable එකයි, setIsVisible කියන setter function එකයි.
  // මුලික අගය true (මුලින්ම text එක පෙන්වන්න).
  const [isVisible, setIsVisible] = useState(true);

  // Text එක toggle කරන function එක.
  const toggleVisibility = () => {
    // current isVisible එකේ ප්‍රතිවිරුද්ධ අගය (true නම් false, false නම් true) දෙනවා.
    setIsVisible(!isVisible);
  };

  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h2>Toggle Text Example</h2>
      <button
        onClick={toggleVisibility}
        style={{
          padding: '10px 20px',
          fontSize: '18px',
          backgroundColor: '#008CBA',
          color: 'white',
          border: 'none',
          borderRadius: '5px',
          cursor: 'pointer',
          marginBottom: '20px',
        }}
      >
        {isVisible ? 'Hide Text' : 'Show Text'}
      </button>
      {/* isVisible true නම් text එක පෙන්වනවා, නැත්නම් නෑ */}
      {isVisible && (
        <p style={{ fontSize: '20px', color: '#333' }}>
          මෙම text කොටස toggle කිරීම සඳහා බොත්තම ඔබන්න. <strong>React State</strong> වල බලය මෙහිදී ඔබට දැකගත හැක.
        </p>
      )}
    </div>
  );
}

export default ToggleText;

මේ උදාහරණයේදී අපි isVisible කියන State variable එකක් භාවිතා කළා. isVisible ? 'Hide Text' : 'Show Text' කියන Ternary Operator එකෙන් Button එකේ Text එකත්, {isVisible && (...) } කියන Conditional Rendering වලින් Paragraph එකත් Control කළා.

මතක තබාගත යුතු දේවල් සහ පොදු ගැටළු (Things to Remember & Common Issues)

useState Hooks භාවිතා කරනකොට මතක තියාගන්න ඕන වැදගත් කරුණු කිහිපයක් තියෙනවා.

Hooks භාවිතයේ නීති (Rules of Hooks)

React Hooks නිවැරදිව වැඩ කරන්න නම්, අපි මේ නීති දෙක පිළිපදින්න ඕන:

    • Loops, conditions (if/else), හෝ Nested functions ඇතුළේ Hooks කැඳවන්න එපා.
    • මොකද React rely කරන්නේ Hooks හැම විටම එකම පිළිවෙලකට කැඳවනවා කියන එක මතයි. මේක කැඩුණොත් bugs එන්න පුළුවන්.
  1. Hooks කැඳවිය යුත්තේ React Functions වලින් පමණි (Only call Hooks from React functions):
    • Functional Components හෝ Custom Hooks ඇතුළේ විතරක් Hooks භාවිතා කරන්න.
    • සාමාන්‍ය JavaScript functions ඇතුළේ Hooks භාවිතා කරන්න බෑ.

Hooks කැඳවිය යුත්තේ ඉහළ මට්ටමෙන් පමණි (Only call Hooks at the top level):


// වැරදි භාවිතය (BAD)
function MyComponent() {
  if (someCondition) {
    const [count, setCount] = useState(0); // Error: Don't call Hooks inside conditions
  }
}

// නිවැරදි භාවිතය (GOOD)
function MyComponent() {
  const [count, setCount] = useState(0); // Call at the top level
  if (someCondition) {
    // ...use count here...
  }
}
        

අනවශ්‍ය නැවත Rendering වීම් (Too Many Re-renders)

React වලින් වැඩ කරනකොට නිතරම එන වැරැද්දක් තමයි Too many re-renders කියන එක. මේක සාමාන්‍යයෙන් වෙන්නේ State update කරන function එකක් කෙලින්ම Component එක render වෙන වෙලාවේදී call කළොත්.


// වැරදි භාවිතය (BAD - Will cause infinite re-renders)
function MyBadComponent() {
  const [count, setCount] = useState(0);

  // setCount(count + 1); // DANGER! This runs on every render, causing an infinite loop.

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={setCount(count + 1)}>Increment</button> {/* Also BAD! */}
    </div>
  );
}

මේ වගේ තැන්වලදී function reference එකක් (function එකම) හෝ anonymous function එකක් (() => {}) භාවිතා කරන්න ඕන. Event එකක් trigger වුණාම විතරයි State update function එක call වෙන්න ඕන.


// නිවැරදි භාවිතය (GOOD)
function MyGoodComponent() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button> {/* Correct: Pass function reference */}
      <button onClick={() => setCount(count + 1)}>Increment Inline</button> {/* Correct: Pass anonymous function */}
    </div>
  );
}

හොඳ පුරුදු සහ ප්‍රශස්තකරණය (Best Practices & Optimization)

React State භාවිතා කරනකොට, හොඳ පුරුදු ටිකක් අනුගමනය කිරීමෙන් ඔබේ Application එක වඩාත් කාර්‍යක්ෂම සහ නඩත්තු කිරීමට පහසු වේවි.

State Updates සඳහා Setter Function එක භාවිතා කරන්න (Always Use the Setter Function for State Updates)

අපි මේක කලිනුත් කිව්වා, හැබැයි මේක ගොඩක් වැදගත් නිසා නැවතත් මතක් කරනවා. කිසිම වෙලාවක State variable එක කෙලින්ම update කරන්න එපා. උදාහරණයක් විදියට, count++ හෝ myObject.property = 'new value' වගේ දේවල් කරන්න එපා. හැමවිටම setter function එක භාවිතා කරන්න: setCount(count + 1) හෝ setMyObject({...myObject, property: 'new value'}).

තවද, ඔබගේ නව State එක පෙර State එක මත පදනම් වන්නේ නම්, setter function එකට callback එකක් දීම වඩාත් ආරක්ෂිතයි. මේක Functional Updates ලෙස හඳුන්වනවා.


// හොඳම භාවිතය: Functional Update
setCount(prevCount => prevCount + 1);

මෙය විශේෂයෙන්ම Multiple State updates එකවර සිදුවන විට හෝ Asynchronous Operations වලදී වැදගත් වෙනවා, මොකද prevCount කියන්නේ update එක සිදුවන මොහොතේ තිබෙන නිවැරදිම State එකයි.

State Immutability (Stateහි අපරිවර්තනීයතාවය)

React State එක update කරනකොට, Array සහ Object වගේ Reference Types වලදී මේ Immutability කියන Concept එක ගොඩක් වැදගත්. React එක State එකක් වෙනස් වුණාද කියලා බලන්නේ, ඒ State variable එකේ Reference එක වෙනස් වුණාද කියලා බලලා. අපි කෙලින්ම Object එකේ property එකක් වෙනස් කළොත්, Reference එක වෙනස් වෙන්නේ නෑ. ඒ නිසා React එකට ඒ වෙනස detect කරන්න බැරි වෙන්න පුළුවන්, re-render වෙන්නේ නැතිව ඉන්න පුළුවන්.

මෙය වළක්වා ගැනීමට, අපි හැමවිටම අලුත් Object එකක් හෝ Array එකක් හදලා, ඒකට අවශ්‍ය වෙනස්කම් කරලා, අලුත් එක setter function එකට දෙන්න ඕන. මේකට අපි Spread Operator (...) එක බහුලවම භාවිතා කරනවා.


import React, { useState } from 'react';

function UserProfile() {
  const [user, setUser] = useState({
    name: 'Kasun',
    age: 30,
    hobbies: ['coding', 'reading']
  });

  const updateUserName = () => {
    // වැරදි භාවිතය: user object එක කෙලින්ම modify කරනවා. React මේ වෙනස detect නොකරන්න පුළුවන්.
    // user.name = 'Amal';
    // setUser(user);

    // නිවැරදි භාවිතය: අලුත් object එකක් හදලා, name property එක වෙනස් කරනවා.
    setUser({
      ...user, // දැනට තියෙන user object එකේ අනිත් properties ටික ඒ විදියටම ගන්නවා.
      name: 'Amal' // name property එක විතරක් වෙනස් කරනවා.
    });
  };

  const addHobby = () => {
    // වැරදි භාවිතය: hobbies array එක කෙලින්ම modify කරනවා.
    // user.hobbies.push('gaming');
    // setUser(user);

    // නිවැරදි භාවිතය: අලුත් array එකක් හදලා, අලුත් hobby එක එකතු කරනවා.
    setUser({
      ...user,
      hobbies: [...user.hobbies, 'gaming'] // දැනට තියෙන hobbies වලට අලුත් hobby එක එකතු කරනවා.
    });
  };

  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h2>User Profile</h2>
      <p>Name: {user.name}</p>
      <p>Age: {user.age}</p>
      <p>Hobbies: {user.hobbies.join(', ')}</p>
      <button onClick={updateUserName} style={{ margin: '5px' }}>Update Name</button>
      <button onClick={addHobby} style={{ margin: '5px' }}>Add Hobby</button>
    </div>
  );
}

export default UserProfile;

State Updates Batching (State Updates සමූහගත කිරීම)

සාමාන්‍යයෙන්, ඔබ එකම Event handler එකක් තුළ useState setter functions කිහිපයක් කැඳවුවහොත්, React විසින් ඒවා Batch කරනවා. ඒ කියන්නේ, React විසින් එක් Event එකකට එක් re-render එකක් පමණක් සිදු කරනවා. මේක Performance එකට ගොඩක් හොඳයි. ඒ නිසා, එකම Event එකකින් State variables කිහිපයක් update කළත්, අනවශ්‍ය re-renders සිදු වෙන්නේ නැහැ.


import React, { useState } from 'react';

function MultiStateUpdate() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('Hello');

  const handleClick = () => {
    setCount(prevCount => prevCount + 1); // 1st update
    setText('Hello World'); // 2nd update
    // React will batch these two updates and re-render only once.
  };

  return (
    <div style={{ textAlign: 'center', marginTop: '50px' }}>
      <h2>Multi State Update Example</h2>
      <p>Count: {count}</p>
      <p>Text: {text}</p>
      <button onClick={handleClick}>Update All</button>
    </div>
  );
}

export default MultiStateUpdate;

අවසන් වශයෙන් (Conclusion)

ඉතින් යාලුවනේ, ඔන්න අපි React State එකයි, useState Hook එකයි ගැන ගොඩක් දේවල් ඉගෙන ගත්තා. මේක තමයි React Application එකක Core එක. මේක හොඳට තේරුම් ගත්තා නම් ඔයාට ඕනෑම සංකීර්ණ UI එකක් පහසුවෙන් හදන්න පුළුවන්.

මතක තියාගන්න වැදගත්ම දේ: State යනු Component එකේ මතකයයි. useState Hook එකෙන් ඒ මතකයට access කරන්න පුළුවන්. ඒ මතකය වෙනස් කරනකොට, හැමවිටම setter function එක භාවිතා කරන්න, ඒ වගේම State immutability ගැන සැලකිලිමත් වෙන්න.

මේ Concepts තව තවත් තේරුම් ගන්න හොඳම විදිය තමයි Practice කරන එක. ඒ නිසා අදම ඔයාගේම React Project එකක් පටන් අරන් මේ දේවල් Try කරලා බලන්න. පොඩි Counter එකක් හදන්න, Todo List එකක් හදන්න, හෝ Quiz App එකක් වුණත් හදන්න පුළුවන්.

මේ ලිපිය ගැන ඔයාගේ අදහස් පහළ Comment Section එකේ දාන්න. ඔයාට ප්‍රශ්න තියෙනවා නම් අහන්න. මේක ඔයාගේ යාළුවන්ටත් ප්‍රයෝජනවත් වෙයි කියලා හිතෙනවා නම් Share කරන්න අමතක කරන්න එපා. ජයවේවා! 🚀