Ref ব্যবহার করে DOM ম্যানিপুলেশন
React স্বয়ংক্রিয়ভাবে DOM আপডেট করে যেন এটি আপনার রেন্ডার আউটপুটের সাথে মিলে যায়, তাই আপনার কম্পোনেন্টের প্রায় সময়ই দরকার হবে না এটা পরিবর্তন করার। তবে, মাঝে মাঝে আপনার React পরিচালিত DOM elements এর প্রয়োজন হতে পারে—উদাহরণস্বরূপ, একটি node কে ফোকাস করতে, স্ক্রল করতে, অথবা এর আকার এবং অবস্থান পরিমাপ করতে। React এ এই ধরণের কাজ করার জন্য কোনো বিল্ট-ইন উপায় নেই, তাই আপনার DOM node এর ref প্রয়োজন হবে।
যা যা আপনি শিখবেন
- কীভাবে React এর পরিচালিত একটি DOM নোড
ref
এট্রিবিউট ব্যবহার করে অ্যাক্সেস করবেন - কীভাবে
ref
JSX এট্রিবিউটuseRef
হুকের সাথে সম্পর্কিত। - কীভাবে অন্য একটি কম্পোনেন্টের DOM নোড অ্যাক্সেস করবেন
- কোন কোন ক্ষেত্রে React এর পরিচালিত একটি DOM নোড পরিবর্তন করা নিরাপদ
একটা নোডকে ref পর্যন্ত নিয়ে যাওয়া
React এর পরিচালিত একটি DOM নোড অ্যাক্সেস করতে, প্রথমে, useRef
হুকটি ইমপোর্ট করুনঃ
import { useRef } from 'react';
এর পর, একে ব্যবহার করে আপনার কম্পোনেন্টের মধ্যে একটি ref ডিক্লেয়ার করেনঃ
const myRef = useRef(null);
সবশেষে, যেই JSX ট্যাগের জন্য আপনি DOM নোড চাচ্ছেন, সেটায় একে ref
এট্রিবিউট হিসেবে পাস করে দিনঃ
<div ref={myRef}>
useRef
হুক একটি অবজেক্ট রিটার্ন করে যার একটি মাত্র প্রপার্টি থাকে current
নামে। প্রাথমিকভাবে, myRef.current
হবে null
। যখন React এই <div>
এর জন্য একটি DOM node তৈরি করে, React এই নোডের একটি রেফারেন্স myRef.current
-এ রাখবে। তারপর আপনি আপনার event handlers থেকে এই DOM node এ অ্যাক্সেস করতে পারেন এবং এর উপর ডিফাইন করা বিল্ট-ইন browser APIs ব্যবহার করতে পারেন।
// আপনি যেকোন ব্রাউজার API ব্যবহার করতে পারেন। উদাহরণস্বরূপঃ
myRef.current.scrollIntoView();
উদাহরণঃ একটা টেক্সট ইনপুটে ফোকাস করা
এই উদাহরণে, বাটনে ক্লিক করলে ইনপুট ফোকাস হবেঃ
import { useRef } from 'react'; export default function Form() { const inputRef = useRef(null); function handleClick() { inputRef.current.focus(); } return ( <> <input ref={inputRef} /> <button onClick={handleClick}> Focus the input </button> </> ); }
এটা করার জন্যঃ
useRef
হুক ব্যবহার করেinputRef
ডিক্লেয়ার করুন।<input ref={inputRef}>
হিসেবে একে পাস করে দিন। এটা React কে বলবে যেন এই<input>
এর DOM নোডinputRef.current
এর মধ্যে রাখা হয়।handleClick
ফাংশনে,inputRef.current
থেকে ইনপুট DOM নোড রিড করুন এবংinputRef.current.focus()
দিয়ে এর উপরfocus()
কল করুন।handleClick
ইভেন্ট হ্যান্ডলারটিonClick
এর সাহায্যে<button>
এ পাঠিয়ে দিন।
যদিও DOM ম্যানিপুলেশন এর জন্যই refs এর ব্যবহার সবচেয়ে বেশি হয়, useRef
হুক React এর বাইরে অন্যান্য জিনিস সংরক্ষণ করার জন্য ব্যবহৃত হতে পারে, যেমন টাইমার ID। State এর মতোই, রেন্ডারে মধ্যবর্তী সময়ে ref ঠিকঠাক থাকে। Refs হল state variables এর মত যেগুলি সেট করার সময় re-render ট্রিগার হয় না। ref সম্বন্ধে পড়ুন ref এর সাহায্যে ভ্যালু রেফারেন্সিং অংশে।
উদাহরণঃ কোন এলিমেন্ট পর্যন্ত স্ক্রল করা
আপনি একটি কম্পোনেন্টে একাধিক ref রাখতে পারেন। এই উদাহরণে, তিনটি চিত্রের একটি ক্যারাসেল আছে। প্রতিটি বাটন ব্রাউজারে ওই ছবির সাথে সম্পর্কিত DOM নোডে scrollIntoView()
মেথড কল করে ছবিটিকে মাঝামাঝি আনে।
import { useRef } from 'react'; export default function CatFriends() { const firstCatRef = useRef(null); const secondCatRef = useRef(null); const thirdCatRef = useRef(null); function handleScrollToFirstCat() { firstCatRef.current.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' }); } function handleScrollToSecondCat() { secondCatRef.current.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' }); } function handleScrollToThirdCat() { thirdCatRef.current.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' }); } return ( <> <nav> <button onClick={handleScrollToFirstCat}> Neo </button> <button onClick={handleScrollToSecondCat}> Millie </button> <button onClick={handleScrollToThirdCat}> Bella </button> </nav> <div> <ul> <li> <img src="https://placecats.com/neo/300/200" alt="Neo" ref={firstCatRef} /> </li> <li> <img src="https://placecats.com/millie/200/200" alt="Millie" ref={secondCatRef} /> </li> <li> <img src="https://placecats.com/bella/199/200" alt="Bella" ref={thirdCatRef} /> </li> </ul> </div> </> ); }
গভীরভাবে জানুন
উপরের উদাহরণে, ref এর একটি পূর্বনির্ধারিত সংখ্যা রয়েছে। যদিও, মাঝে মাঝে আপনার তালিকার প্রতিটি আইটেমের জন্য একটি ref প্রয়োজন হতে পারে, এবং আপনি জানবেন না আপনার কতগুলো থাকবে। এরকম কিছু কাজ করবে নাঃ
<ul>
{items.map((item) => {
// কাজ করে না!
const ref = useRef(null);
return <li ref={ref} />;
})}
</ul>
এর কারণ হুক শুধুমাত্র আপনার কম্পোনেন্টের শীর্ষ-স্তরে ডাকতে হবে। আপনি একটি লুপে, একটি কন্ডিশনে, বা একটি map()
কলের ভিতরে useRef
ডাকতে পারবেন না।
একে এডিয়ে যাবার একটি সম্ভাব্য উপায় হল প্যারেন্ট এলিমেন্টে একটা মাত্র ref নিয়ে যাওয়া এবং তারপরে DOM ম্যানিপুলেশন পদ্ধতিগুলি যেমন querySelectorAll
ব্যবহার করে এটি থেকে individual child node “খুঁজে” বের করা। যদিও, এটি অত্যন্ত নাজুক এবং যদি আপনার DOM কাঠামো পরিবর্তন হয় তবে এটি ভেঙে যেতে পারে।
অন্য একটি সমাধান হলো ref
এট্রিবিউটে একটি ফাংশন পাস করা। এটি ref
callback. নামে পরিচিত। React যখন ref সেট করার সময় হবে তখন এটি আপনার ref callback কে DOM নোড দিয়ে কল করবে, এবং যখন এটি সাফ করার সময় হবে তখন null
দিয়ে ডাকবে। এটি আপনাকে আপনার নিজের একটি array বা একটি Map বজায় রাখতে দেয়, এবং এর মাধ্যমে আপনি তার ইনডেক্স বা কোন ধরণের ID দ্বারা যেকোনো ref অ্যাক্সেস করতে পারেন।
এই উদাহরণটি দেখায় যে আপনি এই পদ্ধতিটি কীভাবে ব্যবহার করে একটি দীর্ঘ তালিকায় যেকোনো নোডে স্ক্রল করতে পারেনঃ
import { useRef, useState } from "react"; export default function CatFriends() { const itemsRef = useRef(null); const [catList, setCatList] = useState(setupCatList); function scrollToCat(cat) { const map = getMap(); const node = map.get(cat); node.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center", }); } function getMap() { if (!itemsRef.current) { // প্রথম ব্যবহারে ম্যাপ ইনিশিয়ালাইজ করুন itemsRef.current = new Map(); } return itemsRef.current; } return ( <> <nav> <button onClick={() => scrollToCat(catList[0])}>Neo</button> <button onClick={() => scrollToCat(catList[5])}>Millie</button> <button onClick={() => scrollToCat(catList[9])}>Bella</button> </nav> <div> <ul> {catList.map((cat) => ( <li key={cat} ref={(node) => { const map = getMap(); map.set(cat, node); return () => { map.delete(cat); }; }} > <img src={cat} /> </li> ))} </ul> </div> </> ); } function setupCatList() { const catList = []; for (let i = 0; i < 10; i++) { catList.push("https://loremflickr.com/320/240/cat?lock=" + i); } return catList; }
এউ উদাহরণে, itemsRef
একটা DOM নোডও রাখে না। বরং এটা আইটেম ID থেকে DOM নোডের একটা ম্যাপ রাখে। তালিকার প্রতিটি আইটেমে ref
callback ম্যাপের আপডেটের বিষয়টা ঠিক রাখে।
<li
key={cat.id}
ref={node => {
const map = getMap();
// ম্যাপে যোগ করুন
map.set(cat, node);
return () => {
// ম্যাপ থেকে সরিয়ে ফেলুন
map.delete(cat);
};
}}
>
এটা আপনাকে ম্যাপ থেকে DOM নোড পৃথকভাবে রিড করতে দেয়।
অন্য একটি কম্পোনেন্টের DOM নোড অ্যাক্সেস করা
আপনি parent component থেকে child component গুলিতে ref pass করতে পারেন অন্য যেকোনো prop এর মতোই.
import { useRef } from 'react';
function MyInput({ ref }) {
return <input ref={ref} />;
}
function MyForm() {
const inputRef = useRef(null);
return <MyInput ref={inputRef} />
}
উপরের উদাহরণে, parent component MyForm
এ একটি ref তৈরি করা হয়েছে, এবং এটি child component MyInput
এ পাস করা হয়েছে। MyInput
তারপর ref টি <input>
এ পাস করে। যেহেতু <input>
একটি built-in component React ref এর .current
প্রপার্টিতে <input>
DOM element সেট করে।
MyForm
এ তৈরি inputRef
এখন MyInput
দ্বারা প্রত্যাবর্তিত <input>
DOM element কে নির্দেশ করে। MyForm
এ তৈরি একটি click handler inputRef
অ্যাক্সেস করতে পারে এবং <input>
এর উপর focus সেট করতে focus()
কল করতে পারে।
import { useRef } from 'react'; function MyInput({ ref }) { return <input ref={ref} />; } export default function MyForm() { const inputRef = useRef(null); function handleClick() { inputRef.current.focus(); } return ( <> <MyInput ref={inputRef} /> <button onClick={handleClick}> Focus the input </button> </> ); }
গভীরভাবে জানুন
উপরের উদাহরণে, MyInput
এ পাস করা ref মূল DOM input element এ পাস করা হয়। এটি parent component কে এর উপর focus()
কল করার সুযোগ দেয়। তবে, এটি parent component কে অন্য কিছু করারও সুযোগ দেয় — উদাহরণস্বরূপ, এর CSS styles পরিবর্তন করা। অস্বাভাবিক ক্ষেত্রে, আপনি exposed functionality সীমাবদ্ধ করতে চাইতে পারেন। আপনি useImperativeHandle
দিয়ে এটি করতে পারেন:
import { useRef, useImperativeHandle } from "react"; function MyInput({ ref }) { const realInputRef = useRef(null); useImperativeHandle(ref, () => ({ // শুধুমাত্র ফোকাস উন্মুক্ত করুন আর কিছু না focus() { realInputRef.current.focus(); }, })); return <input ref={realInputRef} />; }; export default function Form() { const inputRef = useRef(null); function handleClick() { inputRef.current.focus(); } return ( <> <MyInput ref={inputRef} /> <button onClick={handleClick}>Focus the input</button> </> ); }
এখানে, MyInput
এর ভিতরে realInputRef
প্রকৃত input DOM node রাখে। তবে, useImperativeHandle
React কে নির্দেশ দেয় যেন parent component এর ref এর মান হিসেবে আপনার নিজের বিশেষ object প্রদান করে। সুতরাং Form
component এর ভিতরে inputRef.current
শুধুমাত্র focus
method থাকবে। এই ক্ষেত্রে, ref “handle” DOM node নয়, বরং useImperativeHandle
call এর ভিতরে আপনি যে custom object তৈরি করেন।
পুনরালোচনা
- Ref একটি সাধারণ ধারণা, কিন্তু বেশিরভাগ সময় আপনি DOM এলিমেন্ট hold করার জন্য এগুলি ব্যবহার করবেন।
- আপনি
<div ref={myRef}>
পাস করে React কে নির্দেশ দেন যেনmyRef.current
এ একটি DOM node রাখা হয়। - সাধারণত, আপনি ref ব্যবহার করবেন এমন non-destructive কাজের জন্য যেমন focusing, scrolling, বা DOM element measure করা।
- একটি component স্বাভাবিকভাবে তার DOM node গুলি expose করে না। আপনি
ref
prop ব্যবহার করে DOM node expose করার জন্য opt in করতে পারেন। - React দ্বারা পরিচালিত DOM node পরিবর্তন করা এড়িয়ে চলুন।
- আপনি যদি React দ্বারা পরিচালিত DOM node গুলি পরিবর্তন করেন, তবে এমন অংশগুলি পরিবর্তন করুন যেগুলি React এর আপডেট করার কোন কারণ নেই।
SearchInput
এর মতো, আপনার নিজের component থেকে একটি DOM node expose করার জন্য আপনার ref
prop হিসেবে pass করতে হবে।
When React attaches the refs
React এ, প্রতিটি আপডেট দুটি পর্যায়ে ভাগ করা হয়ঃ
- render এর সময়, React আপনার কম্পোনেন্টগুলি কল করে যেন পর্দায় কী থাকা উচিত তা নির্ধারণ করতে পারে।
- commit এর সময়, React DOM এ পরিবর্তনগুলি প্রয়োগ করে।
সাধারণত, আপনি রেন্ডারিং এর সময় ref গুলিতে অ্যাক্সেস করতে চান না। DOM নোডগুলি ধারণ করা ref এর জন্য এটিও প্রযোজ্য। প্রথম রেন্ডারের সময়, DOM নোডগুলি এখনও তৈরি হয়নি, সুতরাং ref.current
হবে null
। আর আপডেট রেন্ডারিং এর সময়, DOM নোডগুলি এখনও আপডেট হয়নি। সুতরাং এখনো তাদের read করার সময় হয় নাই।
React কমিটের সময় ref.current
সেট করে। DOM আপডেট করার আগে, React প্রভাবিত ref.current
মানগুলিকে null
সেট করে। DOM আপডেট করার পরে, React তা অবিলম্বে সম্পর্কিত DOM নোডগুলিতে সেট করে।
সাধারণত, আপনি ইভেন্ট হ্যান্ডলারগুলি থেকে ref গুলি অ্যাক্সেস করবেন। আপনি যদি কোনও ref এর সাথে কিছু করতে চান, কিন্তু এটি করার জন্য কোনও নির্দিষ্ট ইভেন্ট না থাকে, আপনার একটি Effect প্রয়োজন হতে পারে। আমরা পরবর্তী সেকশন গুলিতে Effects সম্পর্কে আলোচনা করব।
গভীরভাবে জানুন
এরকম কোড বিবেচনা করুন, যা একটি নতুন todo যোগ করে এবং স্ক্রিনটি তালিকার শেষ চাইল্ডের দিকে স্ক্রল করে। লক্ষ্য করুন কিভাবে, কিছু কারণে, এটি সবসময় শেষে যোগ করা todo এর ঠিক আগের একটিতে স্ক্রল করেঃ
import { useState, useRef } from 'react'; export default function TodoList() { const listRef = useRef(null); const [text, setText] = useState(''); const [todos, setTodos] = useState( initialTodos ); function handleAdd() { const newTodo = { id: nextId++, text: text }; setText(''); setTodos([ ...todos, newTodo]); listRef.current.lastChild.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } return ( <> <button onClick={handleAdd}> Add </button> <input value={text} onChange={e => setText(e.target.value)} /> <ul ref={listRef}> {todos.map(todo => ( <li key={todo.id}>{todo.text}</li> ))} </ul> </> ); } let nextId = 0; let initialTodos = []; for (let i = 0; i < 20; i++) { initialTodos.push({ id: nextId++, text: 'Todo #' + (i + 1) }); }
এই দুটি লাইনে সমস্যাটি আছেঃ
setTodos([ ...todos, newTodo]);
listRef.current.lastChild.scrollIntoView();
React এ, state আপডেট কিউ করে রাখা হয়। সাধারণত, আপনি এইটাই চাইবেন। তবে, এখানে এটা সমস্যা করে কারণ setTodos
DOM কে সাথে সাথে আপডেট করে না। সুতরাং যখন আপনি স্ক্রল করে তালিকের শেষ এলিমেন্টে যাবেন, তখনো todo যোগ করা হয় নাই। এই কারণে স্ক্রলিং সব সময়ে এক আইটেমের হিসেবে “পিছিয়ে থাকে।“
এই সমস্যাটা সমাধানের জন্য, আপনি React কে DOM সিঙ্ক্রোনাসভাবে আপডেট (“flush”) করতে বাধ্য করতে পারেন। এটা করার জন্য react-dom
থেকে flushSync
ইমপোর্ট করুন এবং state আপডেটকে ঘিরে ফেলুন একটা flushSync
কলের মধ্যেঃ
flushSync(() => {
setTodos([ ...todos, newTodo]);
});
listRef.current.lastChild.scrollIntoView();
এটা React কে নির্দেশ করবে যেন flushSync
দিয়ে ঘেরা কোড চলার সাথে সাথে সিঙ্ক্রোনাস ভাবে DOM আপডেট হয়ে যায়। ফলাফলস্বরূপ, আপনি যতক্ষণে শেষ TODO তে স্ক্রল করে যাবেন তার আগেই এটা DOM এর মধ্যে থাকবে।
import { useState, useRef } from 'react'; import { flushSync } from 'react-dom'; export default function TodoList() { const listRef = useRef(null); const [text, setText] = useState(''); const [todos, setTodos] = useState( initialTodos ); function handleAdd() { const newTodo = { id: nextId++, text: text }; flushSync(() => { setText(''); setTodos([ ...todos, newTodo]); }); listRef.current.lastChild.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); } return ( <> <button onClick={handleAdd}> Add </button> <input value={text} onChange={e => setText(e.target.value)} /> <ul ref={listRef}> {todos.map(todo => ( <li key={todo.id}>{todo.text}</li> ))} </ul> </> ); } let nextId = 0; let initialTodos = []; for (let i = 0; i < 20; i++) { initialTodos.push({ id: nextId++, text: 'Todo #' + (i + 1) }); }
ref ব্যবহার করে DOM ম্যানিপুলেশনের ক্ষেত্রে যা যা মেনে চলা উচিত
Ref হচ্ছে এক ধরণের escape hatch। আপনার শুধুমাত্র “React এর বাইরে পদক্ষেপ নিতে” হলে এর ব্যবহার করা উচিত। এই ধরনের সাধারণ উদাহরণগুলির মধ্যে রয়েছে ফোকাস করা, স্ক্রোল অবস্থান বা ব্রাউজার API গুলি কল করা যা React প্রকাশ করে না।
আপনি যদি ফোকাসিং এবং স্ক্রোলিং এর মতো অবিনাশী কাজগুলিতে স্থাপিত থাকেন, তবে আপনার কোনও সমস্যা হওয়ার কথা নয়। যদিও, আপনি যদি ম্যানুয়ালি DOM পরিবর্তন করার চেষ্টা করেন, তবে আপনি React এর করা পরিবর্তনের সাথে বিরোধিতা ঘটানোর ঝুঁকি নিতে পারেন।
এই সমস্যাটা ব্যাখ্যা করতে, এই উদাহরণে একটা ওয়েলকাম মেসেজ এবং দুটি বাটন আছে। প্রথম বাটনটি conditional rendering এবং state ব্যবহার করে এর উপস্থিতি বদল করে, যেমন আপনি স্বাভাবিকভাবে React এ করেন। দ্বিতীয় বাটনটি remove()
DOM API ব্যবহার করে একে জোর করে DOM থকে সরিয়ে React এর নিয়ন্ত্রণের বাইরে পাঠিয়ে দেয়।
কয়েকবার “Toggle with setState” চাপার চেষ্টা করেন। মেসেজটা হারিয়ে যাবার কথা আবার আসার কথা। এরপরে “Remove from the DOM” এ চাপ দিন। এটা একে জোর করে সরিয়ে ফেলবে। সবশেষে, “Toggle with setState” চাপ দিনঃ
import { useState, useRef } from 'react'; export default function Counter() { const [show, setShow] = useState(true); const ref = useRef(null); return ( <div> <button onClick={() => { setShow(!show); }}> Toggle with setState </button> <button onClick={() => { ref.current.remove(); }}> Remove from the DOM </button> {show && <p ref={ref}>Hello world</p>} </div> ); }
আপনি নিজে DOM এলিমেন্ট সরিয়ে ফেলবার পরে, setState
ব্যবহার করে একে আবার দেখানোর চেষ্টা করলে সিস্টেম ক্র্যাশ করবে। এর কারণ আপনি DOM বদলে ফেলেছেন, এবং React জানে না এর পরে একে কীভাবে পরিচালনা করবে।
React দিয়ে পরিচালিত DOM নোড পরিবর্তন এড়িয়ে চলবেন। যেসব এলিমেন্ট React পরিচালনা করে সেগুলোর পরিবর্তন, চাইল্ড যোগ করা বা চাইল্ড বাদ দেয়ার কারণে ভিজ্যুয়াল ফলাফলে অসামাঞ্জস্য দেখা যেতে পারে বা উপরের মত ক্র্যাশ করতে পারে।
তবে, এর মানে এটা না যে আপনি এটা একদমই করতে পারবেন না। এর জন্য দরকার সতর্কতা। আপনি নিরাপদভাবে DOM এর সেই অংশগুলো পরিবর্তন করতে পারবেন যেগুলো React এর আপডেট করার কোন কারণ নেই। উদাহরণস্বরূপ, যদি JSX এ কোন <div>
সবসময় খালি থাকে, এর চিলড্রেন তালিকায় হাত দেয়ার কোন কারণ থাকবে না React এর। সুতরাং, সেখানে নিজ থেকে এলিমেন্ট যুক্ত করা বা বাদ দেওয়াটা নিরাপদ।
পুনরালোচনা
- Ref একটি সাধারণ ধারণা, কিন্তু বেশিরভাগ সময় আপনি DOM এলিমেন্ট hold করার জন্য এগুলি ব্যবহার করবেন।
- আপনি
<div ref={myRef}>
পাস করে React কে নির্দেশ দেন যেনmyRef.current
এ একটি DOM node রাখা হয়। - সাধারণত, আপনি ref ব্যবহার করবেন এমন non-destructive কাজের জন্য যেমন focusing, scrolling, বা DOM element measure করা।
- একটি component স্বাভাবিকভাবে তার DOM node গুলি expose করে না। আপনি
ref
prop ব্যবহার করে DOM node expose করার জন্য opt in করতে পারেন। - React দ্বারা পরিচালিত DOM node পরিবর্তন করা এড়িয়ে চলুন।
- আপনি যদি React দ্বারা পরিচালিত DOM node গুলি পরিবর্তন করেন, তবে এমন অংশগুলি পরিবর্তন করুন যেগুলি React এর আপডেট করার কোন কারণ নেই।
চ্যালেঞ্জ 1 / 4: ভিডিও চালু এবং বন্ধ করুন
এই উদাহরণে, ভিডিও চালু এবং বন্ধ থাকা অবস্থার সুইচ করার জন্য বাটন একটি state ভ্যারিয়েবল পরিবর্তন করে। তবে, ভিডিও আসলেই বন্ধ বা চালু করার জন্য, state ভ্যারিয়েবল পরিবর্তন করা যথেষ্ট না। আপনাকে <video>
এর DOM এলিমেন্টে play()
এবং pause()
কল করতে হবে। এর সাথে একটি ref যোগ করুন, এবং নিশ্চিত করুন যে বাটনটা কাজ করছে।
import { useState, useRef } from 'react'; export default function VideoPlayer() { const [isPlaying, setIsPlaying] = useState(false); function handleClick() { const nextIsPlaying = !isPlaying; setIsPlaying(nextIsPlaying); } return ( <> <button onClick={handleClick}> {isPlaying ? 'Pause' : 'Play'} </button> <video width="250"> <source src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4" type="video/mp4" /> </video> </> ) }
একটা অতিরিক্ত চ্যালেঞ্জের জন্য, যদি ব্যবহারকারী ভিডিওতে রাইট ক্লিক করে বিল্ট-ইন ব্রাউজার মিডিয়া কন্ট্রোল ব্যবহার করে ভিডিও চালু করে দেয়, সেটার সাথে “Play” বাটন sync রাখুন। আপনি ভিডিওর onPlay
এবং onPause
listen করতে চাইতে পারেন।