احتمالاً نام ویژگی جدید React یعنی hook را شنیدهاید. با این ویژگی میتوان از state و
امکانات دیگر React در مؤلفههای مبتنی بر تابع استفاده کرد.
![React Hooks](https://quera.ir/qbox/view/ewA5GJ7j59/react-hooks.jpg)
جملهای از مستندات React:
> In the longer term, we expect Hooks to be the primary way people write React components.
در این سؤال از شما میخواهیم دو قلاب سفارشی! (custom hook) ساده را پیادهسازی کنید.
# پروژه اولیه
پروژه اولیه را از
[اینجا](https://quera.ir/qbox/download/hqfITbk0HL/simple-hooks.zip)
دانلود کنید.
ساختار فایلهای این پروژه به صورت زیر است.
```
simple-hooks
├── public
│ ├── favicon.png
│ └── index.html
├── src
│ ├── components.js
│ ├── hooks.js
│ ├── index.css
│ └── index.js
├── README.md
├── package.json
└── pnpm-lock.yaml
```
# راهاندازی پروژه
**برای اجرای پروژه، باید `NodeJS` و `npm` (یا `pnpm`) را از قبل نصب کرده باشید.**
- در پوشهی `simple-hooks` ، دستور `npm install` را برای نصب نیازمندیها اجرا کنید.
- **نکته:** برای نصب سریعتر از `pnpm install` استفاده کنید.
- در همین پوشه، دستور `npm start` را برای راهاندازی پروژه اجرا کنید.
- با مراجعه به `http://localhost:3000/` میتوانید نتیجه را ببینید.
- توجه کنید که در این سؤال اجرای پروژهی اولیه با خطا مواجه میشود
و پس از پیادهسازی قسمتهای مربوطه میتوانید نتیجهی نهایی را مشاهده کنید.
# جزئیات
موارد زیر را در فایل `hooks.js` پیادهسازی کنید.
## ۱. شمارندهی حلقوی
useCounter(start, finish) => [c, count]
این قلاب مقدار شروع و پایان شمارنده را به عنوان ورودی میگیرد و یک آرایه شامل مقدار شمارنده و تابعی برای شمردن برمیگرداند. تابع `count` باید مقدار شمارنده را یک واحد اضافه کند. در صورتی که مقدار شمارنده برابر با `finish` باشد با شمارش بعدی مقدار به `start` تغییر میکند.
مثالی از نحوهی استفاده که در پروژهی اولیه نیز آمده است:
```js
function CounterDemo() {
const [c, count] = useCounter(100, 105);
return <div>
<p>{c}</p>
<button onClick={count}>Count</button>
</div>;
}
```
## ۲. پشته
useStack() => {stack, push, pop}
این قلاب یک پشته را پیادهسازی میکند و در خروجی یک شیء شامل مقادیر پشته (آرایهی `stack`)، تابع `push` برای افزودن عنصر به پشته و تابع `pop` برای حذف آخرین عنصر را برمیگرداند.
مثالی از نحوهی استفاده که در پروژهی اولیه نیز آمده است:
```js
const words = ['Apple', 'Banana', 'Cherry', 'Grape'];
export function StackDemo() {
const {stack, push, pop} = useStack();
return <div>
{words.map((word, index) => <button key={index} onClick={() => push(word)}>{word}</button>)}
<button onClick={pop}>» Pop</button>
<ul>
{stack.map((item, index) => <li key={index}>{item}</li>)}
</ul>
</div>;
}
```
نحوهی عملکرد مثالهای بالا را در شکل زیر میبینید.
![React Hooks](https://quera.ir/qbox/view/klXvjpZyoL/react-hooks-demo.gif)
# نکات
- هر کدام از این دو hook را که پیادهسازی کنید، نمرهی آن را خواهید گرفت.
- پس از پیادهسازی، فایل `hooks.js` را ارسال کنید.