React Forms Sinhala Guide | Controlled Components | useState Hook

React applications වල data input ගන්න forms හැමතැනම තියෙනවා නේද? User registration, login, product order කරන තැනකදී වගේ ඕනෑම interaction එකකදී forms නැතුවම බෑ. ඒත්, ඒ ටික හරියට manage කරන්නේ කොහොමද කියන එක සමහරවිට ටිකක් අමාරු වෙන්න පුළුවන්.
HTML forms වලට අපි JavaScript වලින් access කරලා values ගන්නවා වගේ නෙවෙයි React වලදී Forms handle කරන්නේ. React වලදී State කියන concept එක හරහා තමයි forms manage කරන්නේ. අද මේ article එකෙන් අපි React Forms වල හදවත වගේ වෙන Controlled Components කියන්නේ මොකක්ද, ඒවා Uncontrolled Components වලින් වෙනස් වෙන්නේ කොහොමද, useState
Hook එක පාවිච්චි කරලා form State එක manage කරන්නේ කොහොමද, input validation කරන්නේ කොහොමද කියන දේවල් ගැන සවිස්තරාත්මකව සිංහලෙන් කතා කරමු.
මේ tutorial එක අවසානෙදි, ඔයාලට පුළුවන් වෙයි React වලදී forms හදන්න, ඒවායේ State manage කරන්න, validation එකතු කරන්න සහ හොඳම practices මොනවද කියලා තේරුම් ගන්න.
Forms in React – The Basics
සාමාන්ය HTML වලදී අපි form එකක් හදද්දී, input fields වල values Browser එකේ DOM එක විසින්ම handle කරනවා. අපි Form එක Submit කරාට පස්සේ තමයි ඒ values access කරන්නේ. හැබැයි React කියන්නේ UI library එකක්, ඒකේ ප්රධානම දේ තමයි State Management. ඒ නිසා React වලදී අපි form data handle කරන විදිහ ටිකක් වෙනස්.
React වලදී, Form State එක React Component එකේ State එක ඇතුලටම ගේනවා. එතකොට, input field එකක value එක වෙනස් වෙන හැම පාරම, ඒ වෙනස්වීම Component එකේ State එකට update වෙනවා. මේ concept එක තමයි Controlled Components කියන්නේ.
Controlled Components vs. Uncontrolled Components
මේ දෙක තමයි React Forms වලදී අපිට හම්බවෙන ප්රධානම concepts දෙක.
Uncontrolled Components
Uncontrolled Component එකකදී input field එකක data manage කරන්නේ සාමාන්ය HTML Forms වගේම DOM එක විසින්මයි. අපි React State එකක් පාවිච්චි කරන්නේ නෑ input field එකක current value එක handle කරන්න. ඒ වෙනුවට, useRef
Hook එක පාවිච්චි කරලා Form Submit කරන වෙලාවේදී හෝ වෙනත් අවශ්ය වෙලාවකදී DOM එකෙන් input field එකේ value එක direct access කරනවා.
Uncontrolled Components සාමාන්යයෙන් සරල forms වලට, එහෙමත් නැත්නම් අපි input field එකක value එකට React State එකකින් control කරන්න අවශ්ය නැති අවස්ථාවලදී පාවිච්චි කරනවා. උදාහරණයක් විදිහට, file upload input එකක් වගේ දේකට Uncontrolled Component එකක් හොඳයි.
import React, { useRef } from 'react';
function UncontrolledForm() {
const nameInputRef = useRef(null);
const handleSubmit = (event) => {
event.preventDefault();
alert(`Hello, ${nameInputRef.current.value}!`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" ref={nameInputRef} />
</label>
<button type="submit">Submit</button>
</form>
);
}
export default UncontrolledForm;
මේ උදාහරණයෙන් පේනවා nameInputRef.current.value
හරහා අපි direct DOM එකෙන් input එකේ value එක ගන්නේ කොහොමද කියලා.
Controlled Components – The React Way
Controlled Component එකකදී React State එකක් තමයි input field එකක current value එක තීරණය කරන්නේ. input field එකක value එක වෙනස් වෙන හැම පාරම (එනම්, user කෙනෙක් type කරන හැම අකුරක්ම), onChange
event handler එකක් හරහා Component එකේ State එක update වෙනවා. මේ State එක තමයි input field එකේ value
prop එකට bind කරලා තියෙන්නේ.
මේ ක්රමයෙන් Form State එක සම්පූර්ණයෙන්ම React විසින් control කරන නිසා, අපි State Management, Input Validation සහ User Feedback වගේ දේවල් ඉතා පහසුවෙන් implement කරන්න පුළුවන්. මෙය Predictable Behavior එකක් ලබා දෙනවා.
Building a Controlled Form with useState
Controlled Components හදන්න අපි useState
Hook එක පාවිච්චි කරනවා. useState
කියන්නේ React වල Component එකක State එක manage කරන්න පාවිච්චි කරන මූලිකම Hook එකක්.
Initial Setup
මුලින්ම, අපි input field එකක value එක තියාගන්න useState
එකක් define කරමු:
import React, { useState } from 'react';
function SimpleInput() {
const [name, setName] = useState(''); // Initial value is an empty string
// ... rest of the component
}
මෙතනදී name
කියන්නේ State variable එක, setName
කියන්නේ ඒ State variable එක update කරන්න පාවිච්චි කරන function එක. useState('')
කියන්නේ name
කියන State variable එකේ default value එක empty string එකක් කියන එකයි.
Handling a Single Input Field
Single input field එකක් handle කරනකොට, අපි ඒ input field එකට value
prop එකක් සහ onChange
event handler එකක් එකතු කරනවා.
import React, { useState } from 'react';
function SimpleControlledInput() {
const [name, setName] = useState('');
const handleChange = (event) => {
setName(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault(); // Browser default form submission වළක්වනවා
alert(`Hello, ${name}!`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" value={name} onChange={handleChange} />
</label>
<button type="submit">Submit</button>
</form>
);
}
export default SimpleControlledInput;
මෙහිදී, <input type="text" value={name} onChange={handleChange} />
මේ line එක වැදගත්. value={name}
කියන්නේ input field එකේ display වෙන value එක name
State එකට bind කරනවා කියන එකයි. onChange={handleChange}
කියන්නේ input field එකේ value එක වෙනස් වෙන හැම පාරම handleChange
function එක call කරනවා කියන එකයි. ඒ function එක ඇතුලේ අපි setName(event.target.value)
හරහා State එක update කරනවා.
Handling Multiple Input Fields
Form එකක inputs කිහිපයක් තියෙනකොට, ඒ හැම එකකටම වෙනම useState
එකක් පාවිච්චි කරනවා වෙනුවට, හැම input එකකම value එක තියාගන්න පුළුවන් single State object එකක් පාවිච්චි කරන එක වඩාත් සුදුසුයි.
import React, { useState } from 'react';
function MultiInputForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: ''
});
const handleChange = (event) => {
const { name, value } = event.target;
setFormData(prevFormData => ({
...prevFormData,
[name]: value
}));
};
const handleSubmit = (event) => {
event.preventDefault();
console.log('Form Submitted:', formData);
alert(`Welcome, ${formData.name}!`);
};
return (
<form onSubmit={handleSubmit}>
<div>
<label>Name:</label>
<input
type="text"
name="name" // Make sure 'name' prop matches the state key
value={formData.name}
onChange={handleChange}
/>
</div>
<div>
<label>Email:</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
/>
</div>
<div>
<label>Password:</label>
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
/>
</div>
<button type="submit">Register</button>
</form>
);
}
export default MultiInputForm;
මෙම උදාහරණයේදී, handleChange
function එක ඉතා වැදගත්. event.target.name
හරහා input field එකේ name
attribute එක ලබාගෙන, ඒ නමට අදාළ State key එක update කරනවා. setFormData(prevFormData => ({ ...prevFormData, [name]: value }))
මේ line එකෙන් අපි කලින් තිබුණු formData
object එක Spread Operator (...prevFormData
) එකෙන් copy කරලා, අදාල key එක ([name]
) අලුත් value එකෙන් (value
) update කරනවා. මේක තමයි React වල State objects update කරන නිවැරදිම ක්රමය.
Practical Example: A Registration Form with Validation
දැන් අපි කලින් ඉගෙන ගත්තු දේවල් පාවිච්චි කරලා, Validation එක්ක Registration Form එකක් හදමු.
Form Structure and State
අපිට name
, email
, password
කියන inputs ටිකට අමතරව, validation error messages display කරන්න තව State එකක් ඕන වෙනවා.
import React, { useState } from 'react';
function RegistrationForm() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: ''
});
const [errors, setErrors] = useState({}); // Validation errors state
const [isSubmitted, setIsSubmitted] = useState(false);
const handleChange = (event) => {
const { name, value } = event.target;
setFormData(prevFormData => ({
...prevFormData,
[name]: value
}));
// Clear error for the current field as user types
if (errors[name]) {
setErrors(prevErrors => ({
...prevErrors,
[name]: null
}));
}
};
const validateForm = () => {
let newErrors = {};
if (!formData.name) {
newErrors.name = 'Name is required';
} else if (formData.name.length < 3) {
newErrors.name = 'Name must be at least 3 characters long';
}
if (!formData.email) {
newErrors.email = 'Email is required';
} else if (!/^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(formData.email)) {
newErrors.email = 'Email address is invalid';
}
if (!formData.password) {
newErrors.password = 'Password is required';
} else if (formData.password.length < 6) {
newErrors.password = 'Password must be at least 6 characters long';
}
return newErrors;
};
const handleSubmit = (event) => {
event.preventDefault();
setIsSubmitted(true);
const validationErrors = validateForm();
setErrors(validationErrors);
if (Object.keys(validationErrors).length === 0) {
// Form is valid, proceed with submission (e.g., send data to API)
console.log('Form data submitted successfully:', formData);
alert('Registration Successful!');
// Optionally clear the form
setFormData({
name: '',
email: '',
password: ''
});
setErrors({});
setIsSubmitted(false);
} else {
console.log('Form has errors:', validationErrors);
}
};
return (
<div style={{ maxWidth: '400px', margin: '50px auto', padding: '20px', border: '1px solid #ccc', borderRadius: '8px', boxShadow: '0 2px 4px rgba(0,0,0,0.1)' }}>
<h2 style={{ textAlign: 'center', marginBottom: '20px' }}>Register Here</h2>
<form onSubmit={handleSubmit}>
<div style={{ marginBottom: '15px' }}>
<label htmlFor="name" style={{ display: 'block', marginBottom: '5px' }}>Name:</label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleChange}
style={{ width: '100%', padding: '8px', boxSizing: 'border-box', border: `1px solid ${errors.name ? 'red' : '#ccc'}`, borderRadius: '4px' }}
/>
{errors.name && <p style={{ color: 'red', fontSize: '0.9em', marginTop: '5px' }}>{errors.name}</p>}
</div>
<div style={{ marginBottom: '15px' }}>
<label htmlFor="email" style={{ display: 'block', marginBottom: '5px' }}>Email:</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
style={{ width: '100%', padding: '8px', boxSizing: 'border-box', border: `1px solid ${errors.email ? 'red' : '#ccc'}`, borderRadius: '4px' }}
/>
{errors.email && <p style={{ color: 'red', fontSize: '0.9em', marginTop: '5px' }}>{errors.email}</p>}
</div>
<div style={{ marginBottom: '20px' }}>
<label htmlFor="password" style={{ display: 'block', marginBottom: '5px' }}>Password:</label>
<input
type="password"
id="password"
name="password"
value={formData.password}
onChange={handleChange}
style={{ width: '100%', padding: '8px', boxSizing: 'border-box', border: `1px solid ${errors.password ? 'red' : '#ccc'}`, borderRadius: '4px' }}
/>
{errors.password && <p style={{ color: 'red', fontSize: '0.9em', marginTop: '5px' }}>{errors.password}</p>}
</div>
<button
type="submit"
style={{ width: '100%', padding: '10px 15px', backgroundColor: '#007bff', color: 'white', border: 'none', borderRadius: '4px', cursor: 'pointer', fontSize: '1em' }}
>
Register
</button>
</form>
</div>
);
}
export default RegistrationForm;
මේ code එකේදී අපි formData
State එක form values වලටත්, errors
State එක validation errors වලටත් පාවිච්චි කරනවා. validateForm
කියන function එකෙන් inputs ටික validate කරලා errors තියෙනවනම් errors
object එකට එකතු කරනවා. handleSubmit
එකේදී form එක submit කරන්න කලින් validateForm
call කරලා errors තියෙනවද කියලා බලනවා. Errors නැත්නම් තමයි data submit කරන්නේ.
Troubleshooting Common Issues
React Forms එක්ක වැඩ කරද්දී බහුලව එන ගැටලු කිහිපයක් මෙන්න:
Input Not Updating When Typing (Forgetting onChange
)
මේක ගොඩක්ම බහුල වැරැද්දක්. Controlled Component එකක value
prop එකක් දුන්නට, onChange
event handler එකක් දුන්නේ නැත්නම්, input field එක Read-Only එකක් වෙනවා. මොකද, ඔබ type කරන හැම අකුරක්ම State එක update කරන්නේ නැති නිසා, input එකේ value එක වෙනස් වෙන්නේ නෑ.
නිවැරදි:
<input type="text" value={name} onChange={handleChange} />
වැරදි (හැබැයි මේකෙන් Read-Only input එකක් හැදෙනවා):
<input type="text" value={name} />
ඔබේ input එකේ value
prop එකක් තිබෙනවා නම්, අනිවාර්යයෙන්ම onChange
prop එකකුත් දෙන්න ඕනේ.
State Updates Not Reflecting Immediately
React වල setState
functions (setName
, setFormData
වගේ) asynchronous. ඒ කියන්නේ, ඔබ setState
call කරපු ගමන්ම State එක update වෙන්නේ නෑ. ඊළඟ re-render එකේදී තමයි ඒ අලුත් State එක reflect වෙන්නේ.
const handleClick = () => {
setName('New Name');
console.log(name); // This will likely still log the OLD name!
};
අලුත් State එක පාවිච්චි කරන්න අවශ්ය නම්, useEffect
Hook එකක් පාවිච්චි කරන්න පුළුවන්:
import React, { useState, useEffect } from 'react';
function MyComponent() {
const [name, setName] = useState('Old Name');
useEffect(() => {
// This will run AFTER 'name' state has been updated and component re-rendered
console.log('Name has been updated to:', name);
}, [name]); // Dependency array: run this effect when 'name' changes
const handleClick = () => {
setName('New Name');
};
return (
<div>
<p>Current Name: {name}</p>
<button onClick={handleClick}>Change Name</button>
</div>
);
}
Best Practices for React Forms
- Always Prefer Controlled Components: පුළුවන් හැම වෙලාවකම Controlled Components පාවිච්චි කරන්න. මේකෙන් Predictable Behavior එකක් ලැබෙනවා වගේම, State Management, Validation සහ Debugging පහසු වෙනවා.
- Use a Single State Object for Forms: Inputs කිහිපයක් තියෙනකොට, ඒ හැම එකකටම වෙන වෙනම
useState
පාවිච්චි කරනවා වෙනුවට, හැම value එකක්ම තියාගන්න පුළුවන් single object එකක්useState
එකක් පාවිච්චි කරන්න. - Implement Validation: User input එක validate කරන එක අත්යවශ්යයි. Form එක submit කරන්න කලින් හෝ input කරන ගමන් validation එක implement කරන්න.
- Provide User Feedback: Validation errors තියෙනවනම් ඒවා පැහැදිලිව user ට පෙන්වන්න. Invalid input field එක highlight කරන්න.
- Consider Form Libraries for Complex Forms: ඔයාගේ Form එකේ logic එක සංකීර්ණ නම් (complex validation rules, async submission, etc.), Formik, React Hook Form වගේ libraries පාවිච්චි කරන එක ගැන හිතන්න. මේවා Form handling process එක සරල කරනවා.
- Lift State Up: Form data එකට Components කිහිපයකට access කරන්න අවශ්ය නම්, Form State එක පොදු Parent Component එකක තියාගෙන Props හරහා child components වලට pass කරන්න.
Conclusion
අපි අද මේ React Forms & Controlled Components Sinhala Guide එකෙන් React Forms කියන්නේ මොකක්ද, Controlled Components සහ Uncontrolled Components අතර වෙනස, useState
Hook එක පාවිච්චි කරලා Form State manage කරන්නේ කොහොමද, Multiple Inputs handle කරන්නේ කොහොමද, සහ Practical Registration Form එකක Validation implement කරන්නේ කොහොමද කියන දේවල් ගොඩක් විස්තරාත්මකව කතා කළා. ඒ වගේම Common Issues සහ Best Practices කිහිපයකුත් අපි සාකච්ඡා කළා.
දැන් ඔයාට React Forms ගැන හොඳ අවබෝධයක් තියෙනවා ඇති කියලා මම හිතනවා. මතක තියාගන්න, Controlled Components තමයි React Forms වලදී State Management වලට හොඳම ක්රමය. මේ concepts හරියට තේරුම් ගත්තාම, ඕනෑම සංකීර්ණ form එකක් පහසුවෙන් හදන්න ඔයාලට පුළුවන් වෙයි.
අද ඉගෙන ගත්ත දේවල් ඔයාගේ project වලට එකතු කරලා බලන්න. මොන වගේ අත්දැකීම්ද ලැබුනේ? ඔයාගේ ප්රශ්න, අදහස් සහ අත්දැකීම් පහළ comment section එකේ අපිට කියන්න! React Forms ගැන තව මොනවාද ඉගෙන ගන්න කැමති කියලාත් අපිට දන්වන්න!