useState شناخته شده ترین هوک برای استفاده از کامپوننت های کاربردی در React است، اما این فقط یک شروع است. در اینجا هشت قلاب React دیگر و نحوه استفاده از آنها آورده شده است.
- useReducer
- useCallback
- useMemo
- useContext
- useRef
- useEffect
- useLayoutEffect
- useImperativeHandle
- نتیجهگیری
React در میان فریمورکهای جاوا اسکریپت UI همچنان سرعتسنج است. پیشرفتهای زیادی در React وجود دارد، اما مهمترین تغییر در چند سال اخیر، حرکت به سمت اجزای عملکردی بود. اجزای عملکردی برای بسیاری از قابلیت های خود به قلاب ها متکی هستند. رایج ترین قلاب useState
است، اما بسیاری دیگر نیز وجود دارد.
در اینجا نگاهی به هشت قلاب React مفیدی که ممکن است در مورد آنها ندانید و نحوه استفاده از آنها می پردازیم.
useReducer
همه در مورد useState
میدانند، زیرا یک ویژگی اساسی اجزای مبتنی بر کلاس – متغیرهای عضو برای نگهداری وضعیت – را با یک معادل تابعی جایگزین میکند. قلاب useReducer
کاری مشابه انجام میدهد، اما برای سناریوهای پیچیدهتر که در آن جابهجایی حالت بیشتر درگیر است و برنامه از شفافسازی انتقالها سود میبرد. قلاب useReducer
از کاهنده های موجود در Redux الهام گرفته شده است. می توان آن را به عنوان حد وسطی بین سادگی useState
و پیچیدگی یک سیستم مدیریت دولتی مانند Redux در نظر گرفت.
در اینجا مثالی از نحوه کار با قلاب useReducer
آورده شده است. همچنین میتوانید کاهشدهنده را به صورت زنده در این JSFiddle مشاهده کنید.
const {useReducer, Fragment} = React;
const initialState = {
text: "",
isUpperCase: false,
};
const reducer = (state, action) => {
switch (action.type) {
case 'SET_TEXT':
return {
...state,
text: action.text,
};
case 'TOGGLE_UPPER_CASE':
return {
...state,
text: state.text.toUpperCase(),
};
case 'LOWERCASE':
return {
...state,
text: state.text.toLowerCase(),
};
default:
return state;
}
};
const App = () => {
const [state, dispatch] = useReducer(reducer, initialState);
const handleChange = (event) => {
dispatch({ type: 'SET_TEXT', text: event.target.value });
};
const handleToggleUpperCase = () => {
dispatch({ type: 'TOGGLE_UPPER_CASE' });
};
const handleLowerCase = () => {
dispatch({ type: 'LOWERCASE' });
};
return (
<div>
<input type="text" value={state.text} onChange={handleChange} />
<button onClick={handleToggleUpperCase}>Toggle Upper Case</button>
<button onClick={handleLowerCase}>Toggle Lower Case</button>
<p>{state.text}</p>
</div>
);
};
هدف از این مثال این است که متن را از کادر ورودی گرفته و به کاربر اجازه دهید روی دکمهها کلیک کند تا متن را با حروف بزرگ یا کوچک نمایش دهد. کد یک کاهنده جدید را با const [state, dispatch] = useReducer(reducer, initialState);
اعلام می کند. useReducer
تابع کاهنده و Initialstate
را می گیرد و آرایه ای را برمی گرداند که سپس آن را برای حالت دادن و ارسال متغیرها از بین می بریم.
خود کاهنده با این موارد تعریف میشود: const reducer = (وضعیت، عمل) =>
، که یک تابع دو آرگومان میدهد. هر زمان که تابع dispatch در کد فراخوانی شود، وضعیت فعلی را به همراه یک شی اکشن منتقل می کند. در این مورد، شی action دارای یک فیلد نوع است و ما از آن برای تعیین نحوه جهش وضعیت استفاده می کنیم.
در یک برنامه نسبتاً پیچیده، useReducer
میتواند در مدیریت پیچیدگی مفید باشد و حتی میتواند با استفاده از زمینه در سراسر برنامه به اشتراک گذاشته شود. هنگامی که مدیریت useState
به دلیل پیچیدگی برنامه دشوار است، قلاب useReducer
می تواند کمک کند.
useCallback
قلاب useCallback
یک قلاب عملکرد است. عملکردی را می گیرد و تضمین می کند که تنها یک نسخه برای همه تماس گیرندگان بازگردانده شده و مجددا استفاده می شود. اگر تابع گران باشد و به طور مکرر توسط یک حلقه یا مؤلفه های فرزند فراخوانی شود، قلاب useCallback
می تواند عملکرد قابل توجهی را به دست آورد. این نوع بهینه سازی به عنوان یادآوری یک تابع شناخته می شود.
در فهرست ۲، نمونه ای از استفاده از useCallback
برای استفاده از یک تابع در بسیاری از موارد موجود در لیست داریم. این مثال در JSFiddle زنده است.
const List = ({ items }) => {
const [counter, setCounter] = React.useState(0);
const incrementCounter = React.useCallback(() => {
setCounter(counter + 1);
}, [counter]);
return (
<ul>
{items.map((item) => (
<li key={item.id}>
{item} - {counter}
<button onClick={incrementCounter}>Increment</button>
</li>
))}
</ul>
);
};
ما از React.useCallback()
برای ایجاد یک تابع ذخیره شده جدید در incrementCounter
استفاده می کنیم. میتوانیم تابع یادداشتشده را بهعنوان یک تابع عادی در کنترلکننده onClick
در فهرست استفاده کنیم. useCallback()
یک تابع را به عنوان اولین آرگومان می گیرد. در آن عملکرد، ما می توانیم هر کاری را که نیاز داریم انجام دهیم. تفاوت اصلی این است که React به سادگی مقدار حافظه پنهان تابع را برمی گرداند، مگر اینکه چیزی در لیست متغیرهای وابستگی تغییر کرده باشد، که در مثال ما متغیر شمارنده است.
این یک قدرت جادویی گرانبها در مواردی است که نیاز دارید یک عملکرد گران قیمت را بین چندین تماس گیرنده به اشتراک بگذارید، به ویژه اجزای فرزند. به خاطر داشته باشید که وقتی به قلاب بعدی نگاه می کنیم (useMemo
) که useCallback
خود تابع را مخفی می کند. به عبارت دیگر، useCallback
از ایجاد مجدد تابع واقعی هر بار که ظاهر میشود جلوگیری میکند و فقط در صورت لزوم آن را دوباره ایجاد میکند.
useMemo
قلاب useMemo
خواهر و برادر useCallback
است. در جایی که useCallback
تابع را در حافظه پنهان ذخیره می کند، useMemo
مقدار بازگشتی تابع را در حافظه پنهان ذخیره می کند. این یک تمایز ظریف است، اما مهم است.
چه زمانی باید از useMemo
در مقابل useCallback
استفاده کنید؟ پاسخ این است: زمانی که می توانید از useMemo
و زمانی که مجبورید از useCallback
استفاده کنید. قلاب useCallback
زمانی شایسته است که عملکردی که از آن اجتناب میکنید، ایجاد خود تابع در رندر باشد، در حالی که useMemo
از ایجاد مجدد تابع در هر کجا که ظاهر میشود جلوگیری نمیکند. . با این حال، useMemo
اطمینان حاصل می کند که اگر وابستگی ها تغییر نکرده باشند، تابع یک مقدار ذخیره شده در حافظه پنهان را برمی گرداند.
فهرست ۳ useMemo
را در یک مثال نشان می دهد. همچنین میتوانید این مثال را در JSFiddle زنده مشاهده کنید.
const { useMemo, useState } = React;
const ExpensiveComputationComponent = () => {
const [count, setCount] = useState(0);
const computeExpensiveValue = (count) => {
let result = 0;
for (let i = 0; i < count * 10000000; i++) {
result += i;
}
return result;
};
const memoizedValue = useMemo(() => computeExpensiveValue(count), [count]);
return (
<div>
<p>Count: {count}</p>
<p>Expensive Value: {memoizedValue}</p>
<button onClick={() => setCount(count + 1)}>Increment Count</button>
</div>
);
};
در این مثال، تابعی داریم که محاسبه آن هزینه زیادی دارد: computeExpensiveValue
. این بستگی به یک ورودی دارد، count
. میتوانیم از computeExpensiveValue(count), [count])
استفاده کنیم تا به react بگوییم: این تابع را فقط در صورتی اجرا کنید که تعداد تغییر کرده باشد. در غیر این صورت، محاسبات حافظه پنهان را برگردانید.
باز هم، تفاوت با useCallback
واضح نیست. تمایز مهم این است: useCallback
قلابی است برای استفاده زمانی که خود تابع به طور مکرر نمونهسازی میشود و عملکردی را متحمل میشود. در غیر این صورت، useMemo
انتخاب بهتری است.
useContext
در React، context یک محدوده متغیر است که خارج از کامپوننتها وجود دارد و همه اجزا به آن دسترسی دارند. به این ترتیب، این یک فضای جهانی سریع و آسان برای داده های گسترده برنامه است. برای سناریوهای پیچیده، شاید بهتر باشد از یک فروشگاه داده رسمی مانند Redux استفاده کنید، اما برای بسیاری از موارد، context
کافی است. قلاب useContext
نحوه تعامل اجزای عملکردی با زمینه است.
در فهرست ۴، ما دو مؤلفه داریم، Speak
و Happy
که توسط مؤلفه والد برنامه، App
استفاده میشود. کاربر می تواند بین حالت سگ و گربه جابجا شود و از طریق زمینه جهانی، اجزای کودک انتخاب را منعکس می کنند (مثلاً تکان دادن دم در مقابل خرخر کردن). همچنین میتوانید JSFiddle زنده را برای این مثال بررسی کنید.
const { createContext, useContext, useState } = React;
const AnimalContext = createContext();
const Speak = () => {
const { animalType } = useContext(AnimalContext);
return (
<div>
{animalType === 'dog' ? 'woof' : 'meow'}
</div>
);
};
const Happy = () => {
const { animalType } = useContext(AnimalContext);
return (
<div>
{animalType === 'dog' ? 'wag tail' : 'purr'}
</div>
);
};
const App = () => {
const [animalType, setAnimalType] = useState('dog');
const toggleAnimalType = () => {
setAnimalType(prevAnimalType => (prevAnimalType === 'dog' ? 'cat' : 'dog'));
};
return (
<div>
<button onClick={toggleAnimalType}>Toggle animal type</button>
<div>{animalType}</div>
<AnimalContext.Provider value={{ animalType }}>
<Speak />
<Happy />
</AnimalContext.Provider>
</div>
);
};
useRef
قلاب useRef
به شما امکان می دهد مرجعی را خارج از چرخه رندر مدیریت کنید. useState
باعث می شود که موتور React در هنگام تغییر رندر شود، در حالی که useRef
این کار را نمی کند. قلاب useRef
مانند یک ناحیه خاص در کنار React است که میگوید: این متغیر خاص است و بخشی از رابط کاربری واکنشپذیر نیست. رایج ترین مورد استفاده برای useRef
دسترسی مستقیم به DOM و API آن است. به طور معمول، در تفکر واکنشی، از این کار اجتناب می شود و همه چیز باید از طریق موتور واکنشی انجام شود، اما گاهی اوقات اجتناب ناپذیر است.
در فهرست ۵، هنگامی که روی دکمه کلیک میشود، از قلاب useRef
برای نگه داشتن یک مرجع به فیلد ورودی استفاده میکنیم و از روشهای DOM برای تمرکز روی آن و تنظیم مقدار آن استفاده میکنیم. “چیزی شگفتانگیز.” اینجا JSFiddle برای مثال userRef است.
const App = () => {
const inputRef = React.useRef(null);
const handleClick = () => {
inputRef.current.focus();
inputRef.current.value="Something amazing";
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={handleClick}>Focus Input</button>
</div>
);
};
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<App/>
);
useEffect
useEffect
دومین قلاب رایج پس از useState
است. اغلب برای برقراری تماسهای API، تغییر DOM یا انجام اقدامات دیگر (یعنی ایجاد یک اثر) زمانی که چیزی در حالت جزء تغییر میکند، استفاده میشود. به یک معنا، useEffect
به شما امکان می دهد یک متغیر یا متغیرهای واکنشی و رفتاری که برای آنها رخ می دهد را تعریف کنید.
در لیست ۶، یک لیست کشویی برای انتخاب شخصیت جنگ ستارگان تعریف می کنیم. وقتی این مقدار تغییر کرد، یک فراخوانی API با Star Wars API (SWAPI) برقرار می کنیم و داده های شخصیت را نمایش می دهیم. اینجا JSFiddle زنده برای این مثال است.
const { useState, useEffect } = React;
const StarWarsCharacter = () => {
const [character, setCharacter] = useState('Luke Skywalker');
const [data, setData] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(`https://swapi.dev/api/people/?search=${character}`);
const jsonData = await response.json();
setData(jsonData.results[0]);
} catch (error) {
console.error('Error fetching data:', error);
}
};
fetchData();
}, [character]);
const handleCharacterChange = (event) => {
setCharacter(event.target.value);
};
return (
<div>
<h1>Star Wars Character Details</h1>
<select value={character} onChange={handleCharacterChange}>
<option value="Luke Skywalker">Luke Skywalker</option>
<option value="Han Solo">Han Solo</option>
<option value="Princess Leia">Princess Leia</option>
</select>
{data ? (
<div>
<h2>{data.name}</h2>
<p>Height: {data.height}</p>
<p>Mass: {data.mass}</p>
<p>Hair Color: {data.hair_color}</p>
</div>
) : (
<p>Loading...</p>
)}
</div>
);
};
useLayoutEffect
useLayoutEffect
یک قلاب کمتر شناخته شده است که زمانی که نیاز به اندازه گیری DOM رندر شده دارید، وارد عمل می شود. قلاب useLayoutEffect
پس از ترسیم رابط کاربری توسط React فراخوانی می شود، بنابراین می توانید روی آن حساب کنید که به چیدمان واقعی دسترسی پیدا می کند.
در فهرست ۷، ما از useRef
برای برداشتن عنصری از DOM و useLayoutEffect
استفاده میکنیم تا پس از تکمیل رندر، مطلع شویم. سپس، اندازه عنصر را با استفاده از DOM API محاسبه می کنیم. همچنین JSFiddle را برای این مثال ببینید.
const { useState, useRef, useLayoutEffect } = React;
const App = () => {
const [width, setWidth] = useState(null);
const elementRef = useRef(null);
useLayoutEffect(() => {
if (elementRef.current) {
const { width } = elementRef.current.getBoundingClientRect();
setWidth(width);
}
}, []);
return (
<div>
<div ref={elementRef}>Measure Width</div>
<p>Width: {width}</p>
</div>
);
};
useImperativeHandle
گاهی اوقات، شما نیاز دارید که مرجع را مستقیماً به یک مؤلفه دریافت کنید. میتوانید این کار را با useRef
انجام دهید، و اگر میخواهید دسترسی به DOM مؤلفه را نیز فراهم کنید، میتوانید از forwardRef
استفاده کنید. با این حال، گاهی اوقات باید رفتاری را که مؤلفه از طریق مرجع نشان می دهد، سفارشی کنید. برای آن، به قلاب useImperativeHandle
نیاز دارید.
پست های مرتبط
۸ قلاب React دیگر که باید در مورد آنها بدانید
۸ قلاب React دیگر که باید در مورد آنها بدانید
۸ قلاب React دیگر که باید در مورد آنها بدانید