امیدوارم به بهتر شدن کمک کنم. در تلگرام و اینستاگرام پیام بفرست، SeyedAhmaddv - ارشد نرم افزار، توسعه دهنده ری اکت و نکست
استفاده از (prevState state) یا حالت قبلی در ری اکت، مبتدی و پیچیده
عبارتprevState
یک متغیر است. این متغیر در ری اکت به ما این امکان را میدهد که با استفاده از مقدار قبلی یک وضعیت (state)، به راحتی تغییراتی را اعمال کنیم. در زمینههای مبتدی و پیشرفته ری اکت، استفاده از prevState
به منظور بهبود عملکرد و اجتناب از مشکلاتی که از تغییر مستقیم در وضعیت ممکن است ایجاد شود، بسیار حیاتی است.
چگونه از "prevState" معروف برای تغییر state ری اکت خود بدون اورراید یا بازنویسی آن استفاده کنیم!
بیایید با یک مثال ساده و معروف شروع کنیم (برنامه شمارنده)
یک برنامه ساده ری اکت در زیر داریم:
import "./App.css"
import React, { useState } from "react"
const App = () => {
const [mySuperCounter, setMySuperCounter] = useState(0);
const handleIncrement = () => {
setMySuperCounter(mySuperCounter + 1);
setMySuperCounter(mySuperCounter + 1);
setMySuperCounter(mySuperCounter + 1);
};
const handleReset = () => {
setMySuperCounter(0);
};
return (
<div className='App'>
<div>
<button
className='super-button'
type="submit"
={handleIncrement}>
Incrementor
</button>
<button className='super-button' type='submit' ={handleReset}>
State Resettor
</button>
</div>
<div>{mySuperCounter}</div>
</div>
);
};
export default App;
خوب، بیایید کدهای بالا را برای روشن تر شدن توضیح دهم:
در اینجا، ما یک کامپوننت پایه داریم که از state یا حالتی به نام «mySuperCounter» و دو دکمه تشکیل شده است: یکی برای افزایش state و دیگری برای تنظیم مجدد آن به 0 یا همان ریست.
اگر متد "handleIncrement" را بررسی کنیم، ممکن است به نظر برسد که هر بار که روی دکمه "Incrementor" کلیک می کنیم، state به اندازه 3 واحد افزایش می یابد. اما رفتار واقعی متفاوت است. این به این دلیل است که تابع setState ما state قبلی را لغو می کند و یک state جدید ایجاد می کند. به همین دلیل، هنگامی که روی دکمه کلیک میکنیم، وضعیت اولیه سه بار با مقدار یک بازنویسی میشود. به عبارت دیگر، نتیجه ناخواستهای که به آن میرسیم، یک میباشد.
اکنون، بیایید بررسی کنیم که چگونه می توانیم به صورت درستی به حالت قبلی بیافزاییم:
در اینجا کد مربوط به متد handleIncrement آمده است:
const handleIncrement = () => {
setMySuperCounter((prev) => prev + 1);
setMySuperCounter((prev) => prev + 1);
setMySuperCounter((prev) => prev + 1);
};
به راهمان ادامه دهیم! حالا، هنگامی که روی دکمه "Incrementor" کلیک میکنیم، شمارنده ما به ازای هر کلیک به ۳ افزایش مییابد. چرا؟ این به دلیل آرگومان "prev" است که به تابع بازخوانی `setState` در بالاتر ما ارسال شده است.
در موردی که با آن روبرو هستیم، "prev" نشان دهنده state یا حالت قبلی است. بنابراین خط به خط 0 را با 1 و سپس 1 را با 1 و در نهایت 2 را با 1 جمع(ریاضی) میکنیم که در مجموع 3 به دست می آید.
این یک مثال اساسی برای نشان دادن این بود که چگونه آرگومان "prev" به ما کمک می کند تا state یا حالت را به درستی به روز کنیم. حال، بیایید به عمق یک مثال پیچیده تر شیرجه بزنیم!
افزودن کلید/مقدار از یک آرایه به یک آرایه از اشیاء:
ابتدا، یک فایل به نام `sections.js` را ایجاد کنید:
بیایید یک فراخوانی API را با استفاده از یک promise شبیه سازی کنیم:
// sections.js
const mySections = () => {
return Promise.resolve([
{ id: 1, title: "My First Section" },
{ id: 2, title: "My Second Section" },
] );
};
export default mySections;
سپس، فایل `App.js` را به گونهای تغییر میدهم که فراخوانی API را با استفاده از هوک `useEffect` انجام داده و نتیجه را در یک متغیر وضعیت ذخیره کند:
// App.js
import "./App.css"
import React, { useEffect, useState } from "react"
import mySections from "./sections"
const App = () => {
const [sections, setSections] = useState([]);
useEffect(() => {
const loadSections = async () => {
return await mySections();
};
loadSections().then((res) => {
setSections(res);
});
}, []);
return <div className="App"></div>;
};
export default App;
سپس، یک Promise دیگر در یک فایل جداگانه به نام `tools.js` بسازید تا یک فراخوانی API اضافی شبیهسازی شود. اینبار، ما دادههایی را دریافت میکنیم که میخواهم آنها را در بخشهای ذکر شده از قبل، بر اساس `section_id`، ارسال کنم:
// tools.js
const myTools = () => {
return Promise.resolve([
{ id: 1, title: "My Super first tools", section_id: 1 },
{ id: 2, title: "My Super second tools", section_id: 2 },
{ id: 3, title: "My Super third tools", section_id: 1 },
{ id: 4, title: "My Super fourth tools", section_id: 2 },
{ id: 5, title: "My Super fifth tools", section_id: 1 },
{ id: 6, title: "My Super sixth tools", section_id: 2 },
{ id: 7, title: "My Super seventh tools", section_id: 1 },
{ id: 8, title: "My Super eighth tools", section_id: 2 },
]);
};
export default myTools;
حالا، فایل `App.js` را جوری تغییر میدهم تا این تغییرات را اعمال کند:
//App.js
const App = () => {
const [sections, setSections] = useState([]);
useEffect(() => {
const loadSections = async () => {
return await mySections();
};
loadSections().then((res) => {
setSections(res);
});
const loadToolsIntoSections = async () => {
return await myTools();
};
loadToolsIntoSections().then((response) => {
setSections((prev) => {
return prev.map((section) => {
return {
...section,
tools: response.filter((tool) => {
return tool.section_id === section.id;
}),
};
});
});
});
}, []);
return <div className="App"></div>;
};
export default App;
در `App.js` تغییر یافته، من متد `loadToolsIntoSections` را فراخوانی میکنم که یک فراخوانی API دیگر را شبیهسازی میکند. من از متد `setSections` را مجدداً استفاده میکنم و آرگومان "prev" را به تابع بازخوانی میفرستم تا مطمئن شوم که وضعیت قبلی را حفظ میکنم.
سپس روی آرایه sections
یک حلقه map میزنیم تا از طریق هر ابجکت درون آن حرکت کنیم. با استفاده از عملگریا اپراتور spread، یک ابجکت جدید ایجاد کرده و یک کلید اضافی به نام "tools" اضافه میکنیم.
برای پر کردن کلید "tools"، ما response حاصل از فراخوانی API خود را فیلتر میکنیم. ما section_id
هر ابزار را با id
بخش فعلی مقایسه میکنیم. با این کار، هر ابزار را به درستی در داخل بخش مربوطهاش ارسال میکنیم.
این رویکرد به ما این امکان را میدهد که ابزارها را با بخشهای مربوط به آنها به طور موثر ارتباط دهیم. امیدوارم که این توضیح به شما کمک کند که چگونه از prevState
به طور موثر استفاده کنید! با استفاده از آرگومان "prev" ارائه شده در تابع بازخوانی setState
، به راحتی میتوانید وضعیت قبلی را حفظ و بهروز رسانی کنید. این رویکرد مفید است زمانی که نیاز به انجام تغییرات بر اساس وضعیت قبلی دارید و میخواهید از مدیریت و ارسال دادهها به درستی اطمینان حاصل کنید. اگر سوال دیگری دارید، راحت باشید و بپرسید!
مطلبی دیگر از این انتشارات
ساخت برنامه شجره نامه چه داده های ورودی میخواهد؟
مطلبی دیگر از این انتشارات
نوشتن ردیوسر Reducer برای مدیریت حالت شمارنده
مطلبی دیگر از این انتشارات
بیش از 50+ ایده پروژه سطح مبتدی و متوسط ری اکت React 🧙🏻♀️