<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های محمدمهدی بهرامی</title>
        <link>https://virgool.io/feed/@gikdev</link>
        <description>یه برنامه‌نویس کنجاو در حال کاوش، آزمایش و یادگیری 📚 (سایت: https://bahrami85.ir)</description>
        <language>fa</language>
        <pubDate>2026-06-16 07:07:10</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/991520/avatar/ExOrwc.png?height=120&amp;width=120</url>
            <title>محمدمهدی بهرامی</title>
            <link>https://virgool.io/@gikdev</link>
        </image>

                    <item>
                <title>تنظیم نسخه YAML سند OpenAPI در ASP.NET Core</title>
                <link>https://virgool.io/@gikdev/set-yaml-version-of-openapi-in-aspnetcore-tv0ae0aup8t2-tv0ae0aup8t2</link>
                <description>استاندارد OpenAPI، یه استاندارد برای تعریف دقیق APIهای RESTful (یا REST APIها) هست. این استاندارد رو میشه با زبان‌های JSON و YAML نوشت و باهاشون کار کرد.مایکروسافت از نسخه ۹ دات‌نت، پکیج Swashbuckle.AspNetCore رو که از پکیج‌های پیش‌فرض پروژه‌های وب بود حذف کرد، و پکیج رسمی خود که به نام Microsoft.AspNetCore.OpenApi هست رو به پکیج‌های پیش‌فرض پروژه‌های وب اضافه کرد.به طور طبیعی، تنظیماتی که مربوط به OpenAPI میشه هم از نسخه ۹ به بعد دست‌خوش تغییرات زیادی شده و تنظیمات مربوط به فایل سند OpenAPI هم از این قاعده مستثنا نیست. 📃نکته‌ای که هست، اینه که به طور پیش‌فرض، سند OpenAPI پروژه‌های وب در مسیر openapi/v1.json در دسترس هستن، و نسخه YAML اون‌ها به طور پیش‌فرض در دسترس نیست. 🤦🏻‍♂️کد پیش‌فرض پروژه وب دات‌نت (نسخه ۹+)همون‌طوری که می‌بینین، یه متد MapOpenApi هست که فراخوانی شده و خروجی برنامه به این شکل در میاد:سند OpenAPI پروژه پیش‌فرض دات‌نتو مشکلی که چند روز پیش داشتم این بود که نیاز پیدا کردم که نسخه YAML سند OpenAPI رو هم داشته باشم، بتونم اون رو دانلود و ذخیره کنم!بعد امتحان‌کردن چندین راه مختلف، یه راه ساده، راحت، و عالی پیدا کردم که توی چند ثانیه میشه انجامش داد! 👌و اون هم اینه که باید دوباره متد MapOpenApi رو فراخوانی کنیم، و اسم دلخواه سندمون رو توش بنویسم!مثلا:تنظیم نسخه YAML سند OpenAPI برای پروژه API دات‌نتکه خروجی YAML رو هم به برنامه اضافه می‌کنه! ✨نسخه YAML سند OpenAPI پروژه پیش‌فرض وب دات‌نتالبته میشه مسیرها رو ساده‌تر هم کرد... 😊شخصی‌سازی مسیر پیش‌فرض سندهای OpenAPI در پروژه وب دات‌نتشما همین الان یاد گرفتین که چطوری مسیر پیش‌فرض اسناد OpenAPI رو شخصی‌سازی کنین و نسخه‌ی YAML اون‌ها رو هم داشته باشین.سعی می‌کنم توی مقاله بعدی، این رو توضیح بدم که نسخه YAML سند OpenAPI رو برای چی میخواستم،و مطمئنم خیلی نکته بدرد بخوری خواهد بود.امیدوارم براتون مفید بوده باشه، تا مقاله بعدی به امید دیدار! 👋</description>
                <category>محمدمهدی بهرامی</category>
                <author>محمدمهدی بهرامی</author>
                <pubDate>Fri, 10 Apr 2026 02:37:52 +0330</pubDate>
            </item>
                    <item>
                <title>تفاوت useState و useReducer در ری‌اکت</title>
                <link>https://virgool.io/@gikdev/react-usestate-vs-usereducer-gnf6m5nsvkel-gnf6m5nsvkel</link>
                <description>تفاوت useState و useReducer در ریاکتیکی از جالبترین بخشهای ریاکت، هوکها هستن.هوکها قابلیتهای زیادی به برنامههای ما میدن. اونها حتی به ما کمک میکنن از تکرار یه سری از کدها اجتناب کنیم و یه سری کدهایی در برنامهمون داشته باشیم که قابلیت اشتراکگذاری و استفاده دوباره رو دارن.در بحث مدیریت وضعیت (State Management)، هوکهای useState و useReducer دو تا از راه حلهای پیشفرضی هستن که ریاکت جلوی پای ما میذاره.من اول با یه مثال خیلی ساده، useState رو مرور میکنم، بعدش با هم یه مثال پیچیدهتر رو با useState میبینیم. بعد از اون، میرویم سراغ useReducer، تا ببینیم که این هوک چطوری کار ما رو راحتتر میکنه...خب، شما توی یه صفحه، بخش ورودی ایمیل رو در نظر بگیرین:function JoinNewsletterForm() {
  // 👇 ایمیل رو نگه میداره
  const [email, setEmail] = useState(&quot;&quot;) 

  return (
    &lt;form&gt;
      &lt;input 
        type=&quot;email&quot;
        // 👇 - مقدار دهی
        value={email}
        // 👇 - ثبت تغییرات
        ={(e) =&gt; setEmail(e.target.value)}
      /&gt;

      &lt;button type=&quot;submit&quot;&gt; Get Bytes &lt;/button&gt;
    &lt;/form&gt;
  )
}خب این یه مثال ساده هست، نیازی به توضیح خاصی هم نداره!این برنامهای که پایین عکسش رو میبینین، یه برنامهی «لیست کارها» (Todo List) هست که با React درست شده.این صفحه «کارها» در برنامه هست.اگه بخوایم یه نگاهی به کدهای این صفحه بندازیم، با یه همچین چیزی رو به رو میشیم (کد دقیق نیست):function TasksList() {
  // اینجا من دارم کارها رو دریافت میکنم
  const { tasks } = use(TasksContext);

  return (
    &lt;div&gt;
      {tasks.map((t) =&gt; (
        &lt;TaskItem
          key={t.id}
          title={t.title}
          id={t.id}
          isCompleted={t.isCompleted}
        /&gt;
      ))}
    &lt;/div&gt;
  );
}و توی TasksContext این رو داریم:const TasksContext = createContext();

function TasksProvider({ children }) {
  const [tasks, setTasks] = useState([]);

  // تابع تغییر وضعیت انجامشده / نشده کار
  const toggleTaskCompleted = (taskId) =&gt; {
    const clonedTasks = [...tasks];
    const changedTasks = clonedTasks.map((ct) =&gt;
      ct.id === taskId ? { ...ct, isCompleted: !ct.isCompleted } : ct,
    );
    setTasks(changedTasks);
  };
  
  // تابع ایجاد کار
  const createTask = (taskTitle) =&gt; {
    const newTask = {
      id: uuidv4(),
      title: taskTitle,
      isCompleted: false,
    };

    const newTasks = [...tasks, newTask];
    setTasks(newTasks);
  };

  // تابع ویرایش کار
  const editTask = (id, title) =&gt; {
    const editedTasks = [...tasks].map((task) =&gt; {
      if (task.id !== id) return task;

      return { ...task, title };
    });

    setTasks(editedTasks);
  };

  // متد حذف کار
  const deleteTask = (id) =&gt; {
    const editedTasks = tasks.filter((task) =&gt; task.id !== id);

    setTasks(editedTasks);
  };

  return (
    &lt;TasksContext
      value={{
        tasks,
        setTasks,
        toggleTaskCompleted,
        createTask,
        editTask,
        deleteTask,
      }}
    &gt;
      {children}
    &lt;/TasksContext&gt;
  );
}و اینجا ما داریم از useState استفاده میکنیم و کارها رو مدیریت میکنیم.ولی همونطوری که میبینین، تعداد توابع که با کارها کار میکنن، کم نیست، و میشه اینجا برای منظمتر شدن کد، از هوک useReducer استفاده کنیم.اولین مرحله اینه که ببینیم ورودیها و خروجیهای useReducer چی هست:const [ state, dispatch ] = useReducer( reducer, initialState )اولین ورودی یه تابع هست که اسمش reducer هست. کاری که انجام میده اینه که یه دستور میگیره و طبق اون دستور و اطلاعات ضمیمهی اون، تغییرات رو روی وضعیت (state) اعمال میکنه.دومین ورودی یه متغیر یا مقدار میتونه باشه، که حالت اولیه وضعیت هستخروجی این هوک، یه آرایه هست که مقدار اول اون، وضعیت فعلی هست.مقدار دوم آرایه خروجی، تابعی هستش که باهاش به reducer دستور میدیم.خب، با این حساب بریم کدهای TasksContext رو با useReducer بنویسیم.خب، اولین قدم اینه که ببینیم استیت کارهای ما چه شکلی هست.استیت کارهای ما به شکل آرایهای از کارها هستش:interface Task {
  id: string;
  title: string;
  isCompleted: boolean;
}پس، الان شکل initialState و state رو میدونیم.const [ state, dispatch ] = useReducer( reducer, initialState )
//      ^ آرایه کارها
//                                               ^ آرایه کارها

// که اگه بخوایم خودمون بنویسیم، میشه این شکلی:

const [ tasks, dispatch ] = useReducer( reducer, [] )حالا باید ببینیم که چه دستورهایی میشه به reducer داد؟خب، ما هر دستوری که به reducer قراره بدیم، در واقع یه آبجکت هست.// برای تغییر وضعیت انجامشده / نشده کارها
// این دستور رو باید بدیم
{ type: &quot;toggle-completed&quot;, taskId: &quot;flkj2-flkj&quot; }

// برای ایجاد کار جدید
{ type: &quot;create-new&quot;, taskTitle: &quot;فیزیک ص ۳۴&quot; }

// برای ویرایش کار
{ type: &quot;edit-task&quot;, taskId: &quot;flkj-lkjf&quot;, taskTitle: &quot;یادگیری TypeScript&quot; }

// برای حذف کار
{ type: &quot;delete-task&quot;, taskId: &quot;jlfkp-fljasd&quot; }اگه دقت کنین، توی تمام آبجکتهای دستور، ویژگی (property) type (به معنی: نوع) وجود داره.و ما توی نوشتن خود تابع reducer از پراپرتی type استفاده میکنیم تا بفهمیم که چه کدی رو روی استیت فعلی اجرا کنیم.و حالا وقت نوشتن خود تابع reducer هست که این دستورات رو ورودی میگیره، محاسبات رو انجام میده، استیت رو ویرایش میکنه و استیت ویرایششده و جدید رو بر میگردونه:// tasks: استیت فعلی کارها
// action: همون آبجکت دستور ما هست
function tasksReducer(tasks, action) {
  
  // اول پراپرتی تایپ رو چک میکنم، بعد منطق مربوطه رو براش مینویسم
  if (action.type === &quot;toggle-completed&quot;) {
    // اینجا منطق تغییر وضعیت انجامشدن کار رو مینویسیم  
    const clonedTasks = [...tasks];

    const changedTasks = clonedTasks.map((ct) =&gt;
      ct.id === taskId ? { ...ct, isCompleted: !ct.isCompleted } : ct,
    );

    // آخر سر، من چیزی که میخوام جای استیت فعلی بشینه رو بر میگردونم
    return changedTasks;
  }

  // بقیه منطقها...
}و حالا ما این رو هم در هوک useReducer مینویسیم:const [ tasks, dispatch ] = useReducer( tasksReducer, [] )
//                                      ^ طبق چیزی که تعریف کردیممرحله بعد، آپدیتکردن خود TasksContext هست.function TasksProvider({ children }) {
  const [tasks, dispatch] = useReducer(tasksReducer, []);

  return (
    &lt;TasksContext
      value={{
        tasks,
        dispatch,
      }}
    &gt;
      {children}
    &lt;/TasksContext&gt;
  );
}و حالا... جای جالبش رسید.اینجا رو نگاه کنین 👇 بخش مشخصات کار هست:بیاین یه نگاهی به کد دکمه «حذف کن» بندازیم:(کد قبل، با useState):const { deleteTask } = use(TasksContext);

&lt;Btn
  title=&quot;حذف کن&quot;
  color=&quot;danger&quot;
  IconEnd={TrashIcon}
  ={() =&gt; deleteTask(id)}
/&gt;(کد جدید، با useReducer):const { dispatch } = use(TasksContext);

&lt;Btn
  title=&quot;حذف کن&quot;
  color=&quot;danger&quot;
  IconEnd={TrashIcon}
  ={() =&gt; dispatch({
    type: &quot;delete-task&quot;,
    taskId: id,
  })}
/&gt;شاید به نظرتون بیاد که «این که اصلا فرق خاصی نکرده، حتی کدها بیشتر هم شده»ولی،وقتی کارتون به نوشتن برنامههای بزرگتر میرسه،وقتی که استیتهای برنامه خیلی پیچیدهتر میشه،و منطق و تعداد کارهایی که باید روی استیت انجام بشه افزایش پیدا میکنه،وقتی که پروژه رو باید دیباگ کنین چون یه اشتباه کوچولو کردین،متوجه میشین که useReducer،چون تمام منطقهای مربوط به استیت، توی یه جا جمع شده (توی reducer)پس، گسترش و توسعه اون و دیباگکردن reducer راحتتر هست!ولی باید تعادل رو هم حفظ کرد. نباید تند و تند و بیجا از useReducer استفاده کرد.به نظر من، باید هر جایی که دیدین منطقهای مربوط به استیت، داره خیلی زیاد میشه،اونوقت به نظر من موقع خوبی برای استفادهکردن از useReducer هست.خب، یه جمع بندی بکنیم 👇(حوصلهاش رو ندارم، میخوام برم بخوابم فردا برم سرکار... 😁😂)امیدوارم که این مینی-مقاله بدردتون خورده باشه و چیز بدرد بخوری یاد گرفته باشین ازش...تشکر از شما که برای خوندن مقاله من وقت گذاشتین 🌱</description>
                <category>محمدمهدی بهرامی</category>
                <author>محمدمهدی بهرامی</author>
                <pubDate>Fri, 10 Apr 2026 02:37:43 +0330</pubDate>
            </item>
                    <item>
                <title>۹ ماه برنامه نویسی...</title>
                <link>https://virgool.io/fboard/%DB%B9-%D9%85%D8%A7%D9%87-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-gczqpz8dx2el</link>
                <description>از آخرین باری که پست گذاشتم حدود ۹ ماه میگذره. آخرین پستم در مورد ساخت یک دکمه با CSS بود. ولی حالا من خیلی چیز ها یاد گرفتم.به عنوان مثال با این ها آشنا شدم:PythonKotlinHAMLWebpackRubyReactJSVueJSW3.cssBulmaCSSNodeJSPHPSASSStylusTypeScriptCoffeeScriptبه این چیز ها علاقه مند شدم:SvelteJSTailwindCSSDaisyUIViteشروع به تدریس پایتون کردم. و کار با Canva رو هم تا حدی یاد گرفتم. سعی میکنم از این به بعد پست های بیشتری بزارم که استفاده کنید</description>
                <category>محمدمهدی بهرامی</category>
                <author>محمدمهدی بهرامی</author>
                <pubDate>Thu, 31 Mar 2022 07:32:59 +0430</pubDate>
            </item>
                    <item>
                <title>نحوه نشان دادن کد در html بدون اجرای آن</title>
                <link>https://virgool.io/@gikdev/%D9%86%D8%AD%D9%88%D9%87-%D9%86%D8%B4%D8%A7%D9%86-%D8%AF%D8%A7%D8%AF%D9%86-%DA%A9%D8%AF-%D8%AF%D8%B1-html-%D8%A8%D8%AF%D9%88%D9%86-%D8%A7%D8%AC%D8%B1%D8%A7%DB%8C-%D8%A2%D9%86-mhyh5o8yhmvb</link>
                <description>نشان دادن کد در html بدون اجرای آنسلام. من محمد مهدی بهرامی هستم. و امروز می خواهم ترفندی را به شما یاد بدهم تا کدی را در Html  وارد کنید و نمایش دهید بدون اینکه اجرا شود.کافیست کد را در تگ&lt;xmp&gt;بنویسید!آپدیت:استفاده از تگ xmp دیگر پیشنهاد نمیشود. (MDN Web Docs)نشان دادن کد در html بصورت رنگی و بدون اجراکاکافیست آن را در تگ pre یا code یا هر دو نوشته و کاراکتر های &lt; و &gt; را با &amp;gt; و &amp;lt; عوض کنید:&lt;pre&gt;&lt;code&gt;
  &amp;lt;meta charset=&#039;UTF-8&#039; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;یا اینکه میتونید از کنابخانه های رنگ کردن کد مثل Prism, HighlightJS و غیره استفاده کنید.بابت خواندن این ترفند ممنونم. اگر سوال یا مشکلی دارید به این ایمیل بفرستید.bhrm85@yahoo.com</description>
                <category>محمدمهدی بهرامی</category>
                <author>محمدمهدی بهرامی</author>
                <pubDate>Sun, 04 Jul 2021 17:16:15 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش ساخت دکمه با CSS</title>
                <link>https://virgool.io/@gikdev/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%B3%D8%A7%D8%AE%D8%AA-%D8%AF%DA%A9%D9%85%D9%87-%D8%A8%D8%A7-css-akr0renxomcw</link>
                <description>آموزش ساخت دکمه با css و htmlسلام به کد دوستان عزیز. من بهرامی هستم و امروز می خواهم ساختن دکمه های بالا را با استفاده از HTML و CSS به شما یاد بدهم.گفتن این نکته رو هم ضروری می دونم که شما باید مهارت های زیر را برای ساختن دکمه بالا داشته باشید: آشنایی با html و cssآشنایی با ویرایشگر های کد و IDE هاآشنایی با مرورگرآشنایی با روش های استفاده CSS در HTMLبلد بودن زبان انگلیسی حداقل در حد مبتدی(لینک ها)می خواهم html و css را به زبان فارسی یاد بگیرم:اپلیکیشنhtml http://cafebazaar.ir/app/?id=com.diamond.hlaf&amp;ref=share اپلیکیشن css http://cafebazaar.ir/app/?id=ir.diamondcorp.cla&amp;ref=share فیلم و جزوه html https://sariasan.com/html/free-full-lessons-2/ فیلم و جزوه css https://sariasan.com/css1/css-free-full-lessons/ می توانم html و css را به انگلیسی بخوانم:اپلیکیشن https://myket.ir/app/nabilsoft.com.learnwebdevelopment (کد ها)1:
&lt;button id=&amp;quota&amp;quot&gt;BUTTON&lt;/button&gt;
2:
	#a  {      		width: 200px;      		height: 50px;      		border-radius: 25px;      		border-color: red;      		color: red;      		background: none;      		}
3:
		#a:focus  {      			width: 300px;      			border-color: #0f5;      			color: #0f5;      			transition:0.5s;
4:
body {      	background-color: #111;      	text-align: center;      }بریم سراغ آموزش:ابتدا یک فایل button.html ایجاد و اعلان DOCTYPE و بقیه تگ های مورد نیاز را وارد کنید. کد 1 را در تگ &lt;body&gt; کپی کنید. این کد حاوی تگ دکمه، شناسه تگ و کلمه دکمه بین تگ شروع و پایان هستش.در تگ &lt;style&gt; که در تگ &lt;head&gt; وارد کرده اید، کد 2 را وارد کنید. در کد 2، a# را داریم که سلکتور دکمه ماست.خاصیت width به معنای طول می باشد، که می توانید با پیکسل مشخص کنید.خاصیت height به معنای عرض می باشد، که آن را هم می توان با پیکسل نوشت. خاصیت border-radius که با پیکسل مشخص می شود توانایی این را داراست که به دکمه ی ما حالت گرد می دهد.خاصیت border-color رنگ حاشیه دکمه ما را تغییر می دهد(رنگ در سی اس اس). اگر بعد  خاصیتbackground کلمه none را بگذاریم پس زمینه دکمه حذف می شود یا به عبارت دیگر پس زمینه دکمه با پس زمینه صفحه یکی می شود.سپس بعد نوشتن کد 2، به خط بعدی رفته و کد 3 را وارد کنید.در کد سه بعد a# عبارت :focus برای وقتی هستش که میخواهیم وقتی دکمه کلیک شد دکمه به آن حالت تغییر کند.دوباره ما از خاصیت width استفاده کرده ایم تا بعد کلیک دکمه، سایز از 200 پیکسل به 300 پیکسل تغییر کند.نکته:لازم نیست خواصی که نمی خواهید تغییر کنند را در focus هم وارد کنید.خاصیت transition کمک می کند که تعیین کنیم که دکمه بعد کلیک شدن با چه سرعتی خواص تعیین شده را به خود بگیرد.کد 4 رو هم که به body مربوطه یادتون نره.خاصیت text-align کمک می کند که موارد داخل تگ &lt;body&gt; را راست چین چپ چین یا وسط چین کنیم.سپس کد را ذخیره و اجرا کنید و لذت ببرید.کسایی که نمی خوان زحمت بکشن و یاد بگیرن میتونن کل کد رو از زیر کپی کنن.&lt;!DOCTYPE html&gt;&lt;html lang=&amp;quoten&amp;quot&gt;   &lt;head&gt;      &lt;title&gt;Button&lt;/title&gt;      &lt;style&gt;      body {      	background-color: #111;      	text-align: center;      }            	#a {      		width: 200px;      		height: 50px;      		border-radius: 25px;      		border-color: red;      		color: red;      		background: none;      		}       		      		#a:focus {      			width: 300px;      			border-color: #0f5;      			color: #0f5;      			transition:0.5s;      		}      	&lt;/style&gt;   &lt;/head&gt;   &lt;body&gt;      &lt;button id=&amp;quota&amp;quot&gt;BUTTON&lt;/button&gt;   &lt;/body&gt;&lt;/html&gt;
(استفاده از متن بالا کاملا مجاز است)اگر خوشتون اومد لایک کنید یا اگر سوالی دارید بپرسید حتما من یا دیگران پاسخ خواهیم داد. ممنون.</description>
                <category>محمدمهدی بهرامی</category>
                <author>محمدمهدی بهرامی</author>
                <pubDate>Fri, 25 Jun 2021 22:30:11 +0430</pubDate>
            </item>
            </channel>
</rss>