AG Coding
1.28K subscribers
488 photos
52 videos
8 files
241 links
Some Challenges And Applications On Frontend Development
maded By @abdoelazizgamal
Don't Forget Follow And Subscribe My
Youtube channel
https://www.youtube.com/c/AbdoELAzizGamal?sub_confirmation=1
Download Telegram
AG Coding
إيه الجديد في JavaScript ال ECMAScript® 2024 (ES15) متستغربش :( إنت بتكبر والjs بتكبر معاك ! الكلام دا كله قالوا إن هيطبق السنة دي :( إن عشنا وكان لنا من العمر بقية نبدأ بسم الله بأول حاجة Temporal.Now.Instant() في استبيان State of JS 2022، السؤال…
part 2 !!!!!!
من ال js بتكبر وإنت بتكبر معاها
تالت حاجة هي
Records and Tuples
لو إنت جاي من لغة برمجة زي بايثون ف هتسأل هل Tuples موجودة ف ال js ، الحقيقة لا بس تقدر تعملها simulation بإستخدام Object.seal()
let arr = new Array(1, 0, 0);
let tuple Object.seal(arr)

أو هتستخدم ال Proxy
طب إيه الهدف إنهم يضيفوا حاجة زي دي للjs ببساطة كل الهدف إنها تضيف immutable data structures to JavaScript.

ال (Tuples) شبه الِarrays - لستة مترتبة من القيم - لكن مش ممكن تتغير (immutable). ده معناه إن كل قيمة في Tuples لازم تكون يا إما قيمة (primitive) يا إما Record تاني أو Tuple تاني (مش arrays أو objects لإنهم ممكن يتغيروا في الجافاسكريبت).

الTuple بيتعمل بطريقة مشابهة للأراي العادية، بس بتحط علامة الشباك (#) في الأول:
const heroes = #["Batman", "Superman", "Wonder Woman"]
بعد ما تعمل التوبل ده، مش ممكن تضيف قيم تانية أو تشيل قيم. القيم نفسها كمان مش ممكن تتغير.

ال (Records) شبه الobjects - مجموعة من ال (key-value pairs) - لكن برضه مش ممكن تتغير. بتتعمل بطريقة مشابهة للobjects، بس برضه بتحط علامة الشباك في الأول:
const traitors = #{
diane: false,
paul: true,
zac: false,
harry: true
}

الRecords هتستخدم الـ dot notation عشان توصل للproperties and methods
traitors.paul
<< true

وكمان الـ square bracket notation اللي بتستخدم مع ال arrays ممكن تستخدمها مع الtuples:
heroes[1]
<< "Superman"

بس لإنهم ثابتين (immutable)، مش هتقدر تعدل أي خصائص:

traitors.paul = false
<< Error

heroes[1] = "Supergirl"
<< Error


الimmutability of tuples and records يعني إنك هتقدر تقارن بينهم بسهولة باستخدام operator(===):

heroes === #["Batman", "Superman", "Wonder Woman"];
<< true

حاجة لازم تاخد بالك منها إن ترتيب الproperties مش بيهم لما تيجي تقارن بين الrecords
traitors === #{
ross: false,
zac: false,
paul: true,
harry: true
};
// still true, even though the order of people has changed
<< true
:
الترتيب بيفرق في الtuples لإنهم لستة مرتبة من البيانات:
heroes === #["Wonder Woman", "Batman", "Superman"];
<< false
This media is not supported in your browser
VIEW IN TELEGRAM
Topic دسم
مش هتلاقيه كتير ، مستني إيه خش إتفرج وسيب رأيك🖤
https://youtu.be/VPHgxaOAIPo
دا كنز حرفيًا ،
دا interactive visualizer هيساعدك تفهم ال dom event systems

https://domevents.dev/
🔥1
لو هنتكلم عن الmemory management بشكل عام ف لغات البرمجة بتتقسم لشقين ، شق بيخليك إنت كمبرمج تتحكم manualluy ب إيدك وتخصص الmemory و ت free up زي ال c++ وال c عن طريق functions زي malloc و free وغيرهم وتقدر تستخدم libraries تضيف نوع من أنواع ال garbage collection زي boehm-demers-weiser ، بس دي مش جزء من اللغة نفسها ،
ولغات تانية بتعمل دا بشكل automated عن طريق الgarbage collection زي الjava و python و js ، فيه شق تالت بقي خرج برا الصندوق وفكرت بشكل مختلف زي Rust ، عملت نظام خاص بيها إسمه الownership بيطبق وقت الcompile time وبيتكون من شوية principles
زي الsingle owner وال scope و ال borrowing وال safe references ،
تعال بقي نتكلم ف حبيبتنا ،


Garbage Collection - Memory Management in Js

لو لقيت نفسك في موقف المتصفح يقفل فجأة أو ي freeze ، ممكن تتسائل إيه الأسباب اللي ورا ده. ممكن تقول السبب أخطاء في js code ، وفعلاً ده صح في أغلب الأوقات. فيه كذا طريقة js ممكن تستهلك بيها limit of a browser’s memory capacity
الحاجات دي بتتسمى memory leaks (تسريبات الذاكرة) وبتأثر بشكل كبير على تجربة المستخدم. واحدة من الطرق الشائعة اللي اللغات البرمجية بتستخدمها لمكافحة الحالة دي هي استخدام garbage collection.

ببساطة، الـ garbage collection هي نوع من automatic memory management . بتسترجع الذاكرة اللي بيشغلها الobjects اللي مبقتش مستخدمة في execution .

فهل جافاسكريبت بتستخدم garbage collection؟

أيوة، جافاسكريبت بتستخدم طريقة لgarbage collection بشكل دوري لما يبقي مفيش references للunused object or variable . العملية دي بتتم بشكل automated وبتساعد في ضمان إن المتصفح ميتحملش overload في الذاكرة ويتوقف.

العملية دي بتمشي كالتالي:

- تخصيص مساحة الذاكرة المطلوبة للبرنامج (Allocation)
- processing و execution للأكواد.
- تحرير مساحة الذاكرة من ال variables و objects اللي مبقتش مستخدمة.
علشان نعرف إيه ال variables و objects اللي محتاجة تتحذف، بيستخدموا اتنين algorithms رئيسيتين اسمهم Mark-and-sweep

الalgorithms lifecycle دي بتتكون من مرحلتين

مرحلة التعليم (Mark Phase)

المرحلة دي بت scans ال variables و objects المختلفة وبتتأكد إنها referenced من حاجة تانية في البرنامج. لو مفيش reference ، بتحذف الobject من الذاكرة.


مرحلة الكنس (Sweep Phase)

بتنضف ال heap memory من كل الobjects اللي ملهاش reference.
أي object قيمته false بيتشال من ال heap memory.

العملية دي بتحصل بشكل automated لكن ده مش معناه إن ال JavaScript developer مش لازم يقلق منها. العكس صحيح، تجاهلها ممكن يكون ضار بتنفيذ البرنامج، تعالوا نستكشف الموضوع ده أكتر.


إيه هو الـ Memory Leak في الJavaScript ؟
زي ما وضحنا دور الـ garbage collector في منع الmemory leaks ، إيه هو الـ memory leak بالتحديد؟

ببساطة، الـ memory leak هو البيانات اللي الcompiler نسي يستخدمها. ممكن نعرفها ك memory مبقتش مطلوبة لتنفيذ برنامجك لكنها محصلهاش released عشات ت free up ال memory capacity.

لما بتcreate ال objects وvariables ، الcompiler بيستهلك بعض من الmemory علشان يتابع المعلومات دي.
الـ garbage collector بيكون عنده القدرة إنه يعرف امتى المتغير مبقاش مطلوب لتنفيذ البرنامج.

الـ memory leak بيحصل لما البرنامج ميعدش محتاج المتغير اللي اتعمل، لكن run time environment (المتصفح) بتعتقد إنك لسه محتاجه. ده بيسبب تعارض بين بيئة التشغيل وتنفيذ الكود. مقارنةً بخطأ typical runtime error ، الـ memory leak غالبًا مش بتظهر في شكل خطأ واضح. وده لأنهم مش بينتجوا عن كود مش valid بشكل صريح، لكن من عيب منطقي في الstructure للكود.
في النهاية، ده بيسبب بطء في أداء التطبيق وغالبًا بيوصل لتعطل أو تهنيج المتصفح بالكامل.
بعض السيناريوهات الشائعة اللي بتسبب الـ memory leak في الJavaScript واللي لازم تتجنبها كdeveloper
Infinite Loops
يمكن تكون أشهر سبب لmemory leaks ، الinfinite loops بتسبب تعطل المتصفح خلال تفاعل المستخدم. جرب تحط الكود ده في ال developer console debugging tools
while (true) {
//your code
}

تنفيذ الكود ده هيخلي المتصفح يهنج. لكن الكود ده معمول علشان يسبب تmemory leak ومش العادي إنك تلاقيه في production code . الغالب إن تايمر منسي يخلق السيناريو ده واستخدام setInterval غالبًا ورا الحالات دي.
خد التايمر ده كمثال:
var counter = 10;
setInterval(function(){
console.log(counter);
counter--;
if (counter === 0) {
console.log("I am running!");
}
}, 1000);

من الوهلة الأولى، ممكن تفترض إن الloop دي هتتوقف بعد 10 مرات. لكن setInterval مش بيعمل غير إنه يمرر function محددة. بنفسه، مفيش stop أو break ! ، والموضوع ده ممكن يتنسى.

لما نستخدم clearInterval، نقدر نوقف التايمر . بياخد بارامتر واحد بيحدد ال function المحددة اللي عايز توقفها.
var counter = 10;
var runningFunction = setInterval(function(){
console.log(counter);
counter--;
if (counter === 0) {
console.log("I am running!");
clearInterval(runningFunction);
}
}, 1000);

إضافة clearInterval لما بنستخدم setInterval ممكن تمنع memory leaks غير الضرورية في كودك.

الـ Closures
زي ما ممكن تكون عارف، الـ closures هي ركن أساسي من أساسيات جافاسكريبت. الـ closures بتتسمى كتير function بترجع function . الفكرة الرئيسية إن ال inner function عندها access لمتغيرات ال
outer functions
خلينا نبين ده بمثال:


function buildName(name) {
var greeting = "Hello, " + name + "!";
var sayHello = function() {
var welcome = greeting + " Welcome!";
console.log(greeting);
};
return sayHello;
}


ده مثال بسيط لعمل closure
buildName بيعمل متغير في local scope بتاعه
sayHello موجودة ك function في الinner scope (جوا sayHello).
sayHello لسه عندها access لمتغير greeting حتى لو اتعمل في scope مختلف.
الـ closures فعالة جدًا لما بتحاول تكتب كود يكون تكراري وكذلك الكود اللي مش بيكرر نفسه.

إزاي الـ closures ممكن تسبب memory leak ؟
الـ memory leak بيحصل في الـ closure لو واحد من المتغيرات اللي حصلها declared في الouter function بقت متاحة للinner nested function.
ال reference ده لازم يفضل موجود في الذاكرة علشان ال inner nested function توصل للمتغيرات دي. عشان كده، المتغيرات دي مش هتتحذف بالـ garbage collector وده ممكن يسبب memory leak .

الglobal variables الغير مقصودة (Accidental )
من السهل الوقوع في فخ ال memory leak بسبب وجود global variables في الكود.

هنا مثال على إنشاء global variables:
var createdVariable = "This is a global variable";

function myFunction() {
// المتغير createdVariable متاح هنا جوا myFunction()
}


أي متغير اتعمل في الtop scope level of the document بيبقى global.

في المثال ده، createdVariable اتعمل برا الscope بتاع myFunction، ومن ثم مفيش local scopes تانية، globalVariable بيعيش في الtop level.

الGlobal variables مش بتتحذف بالـ garbage collector. لازم ناخد الحذر دايمًا لما نستخدم الGlobal variables في كودنا.

فكر في window object في المتصفح، ده في الأساس highest tier of scope اللي الjs بتعيش فيه.

ممكن تجرب ده بفتح ال dev tools وكتابة this في console.

ال window object بيرجع لنا هنا، بيبين إن current scope هو global scope.

أي متغيرات معلنة بشكل global ممكن تعملها access من كل الscripts والlibraries والfunctions في JavaScript document . وده واحد من الأسباب الرئيسية ليه مش بيتجمع بالـ garbage collector.
ألحل العملي بقي عشان أقلل من ال Global variables
استخدام use strict
تعتمد ع ال Block scope إستخدام let بدل var
👍2
النهارده كنت محتاج أكتشف إذا كان المستخدم مشغل adblocker ولا لأ. ممكن تسأل ليه؟ في الحالة دي، كنت عاوز أتحقق من بعض بيانات المستخدم عن طريق نظام خارجي، لكن الـ adblockers زي Ghostery هتمنع الاتصال دا. مثال ع المواقع العالمية اللي بتستخدم اتصالات بأنظمة خارجية هو موقع Facebook اللي بيتتبع تفاعل المستخدمين عن طريق Google Analytics. لو كان المستخدم مشغل adblocker، الطلبات دي ممكن تتمنع.
عشان كده، جربت أدور كتير عشان ألاقي طرق لاكتشاف الـ adblockers.
الطريقة الأولى اللي استخدمتها هي JavaScript onError Callback. بنضيف سكريبت وهمي في الـ HTML، والـ adblocker هيمنعه. لو السكريبت اتمنع، الfunction بتاعتنا هتشتغل.
<script
async
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
onerror="adBlockFunction();"
></script>
الfunction اللي بتشتغل لما السكريبت يتمنع:


const adblocker = document.getElementById('adblock-message');
adblocker.style.display = 'block';
وفي الـ HTML بنضيف ديف مخفي يظهر الرسالة لو تم اكتشاف الـ adblocker.

<div id="adblock-message" class="hidden">Sorry, you have your adblocker on!</div>


الطريقة الثانية: JavaScript File Check
هي إننا نعرف سكريبت JavaScript زي كده:

<script src="/js/ads.js"></script>
جوا الملف دا نكتب:


var canRunAds = true;


ونستخدم الكود دا عشان نتحقق:



if (window.canRunAds === undefined) {
const adblocker = document.getElementById('adblock-message');
adblocker.style.display = 'block';
}



الطريقة الثالثة: استخدام div ثابت
طريقة تالتة هي إنك تستخدم "ad" ثابت في الـ HTML:


<div
id="detect"
class="ads ad adsbox doubleclick ad-placement carbon-ads"
style="background-color:red;height:300px;width:300px;position: absolute;left:0;top:0;"
>
 
</div>
وبعدين نتحقق من الارتفاع:


const testAd = document.getElementById('detect');
window.setTimeout(function() {
if (testAd.offsetHeight === 0) {
const adblocker = document.getElementById('adblock-message');
adblocker.style.display = 'block';
}
testAd.remove();
}, 100);
كل الطرق دي مفيدة، بس لازم تجربها على كذا متصفح وكذا نوع من الـ adblockers عشان تتأكد إنها بتشتغل في كل الحالات.
1
هتكلم عن حاجة مش واخدة حقها في ال js وناس كتير متعرفهاش وهي ال MutationObserver
الـ MutationObserver بيتيح لك تراقب التغييرات اللي بتحصل في DOM بتاعك بشكل فعال وسريع
يعني إيه MutationObserver؟
MutationObserver هي API موجودة في JavaScript بتسمح لك تراقب أي تغيير بيحصل في DOM nodes. يعني لو حصل إضافة، حذف، أو تعديل لأي عنصر في الصفحة، الـ MutationObserver هيقدر يكتشف دا.
استخداماته
مراقبة تغييرات في الـ DOM: زي ما قولنا، لو فيه تغيير في أي عنصر في الصفحة، تقدر تعرف وتتصرف بناءً عليه.
تحديث الـ UI تلقائياً: لو عندك عناصر في الصفحة بتتغير كتير، ممكن تستخدم الـ MutationObserver عشان تعمل تحديث تلقائي للـ UI.
إزاي تستخدم الـ MutationObserver؟
في البداية، بنعرف الـ MutationObserver نفسه. الـ MutationObserver بياخد callback function ك Argument . الـ callback دي هي اللي بتتنفذ كل ما يحصل تغيير في الـ DOM.
const observer = new MutationObserver((mutationsList, observer) => {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
console.log('A child node has been added or removed.');
} else if (mutation.type === 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
});
تاني حاجة ال callback function
الـ callback function اللي بنمررها للـ MutationObserver بتاخد 2 Arguments
mutationsList: قائمة بكل التغييرات اللي حصلت.
observer: الـ observer نفسه اللي بيتنفذ الكود من خلاله.
تالت حاجة التعامل مع التغييرات
بنستخدم for...of loop عشان نمر على كل التغييرات اللي في mutationsList ونتعامل معاها بناءً على نوع التغيير
childList: لو التغيير في الأطفال (إضافة أو حذف عناصر).
attributes: لو التغيير في خصائص العنصر (زي تعديل خاصية معينة).
رابع حاجة وهي تحديد العنصر والإعدادات
دلوقتي بنحدد العنصر اللي عايزين نراقبه والإعدادات اللي عايزين نتابعها. بنستخدم observe method للـ observer عشان نبدأ المراقبة.
const config = { attributes: true, childList: true, subtree: true };
const targetNode = document.getElementById('some-id');
observer.observe(targetNode, config);
المعاملات بتاعت observe:
targetNode: العنصر اللي عايزين نراقبه.
config: إعدادات المراقبة، ودي عبارة عن object بيحدد نوع التغييرات اللي عايزين نتابعها:
attributes: لو عايزين نتابع التغييرات في خصائص العنصر.
childList: لو عايزين نتابع التغييرات في الأطفال (إضافة أو حذف عناصر).
subtree: لو عايزين نتابع التغييرات في كل الnodes اللي تحت العنصر ده.
خامس حاجة إيقاف المراقبة
لو حبينا نوقف المراقبة في أي وقت، بنستخدم disconnect method للـ observer.
observer.disconnect();
دي مهمة عشان ال memory leaks اللي إتكلمنا عليها قبل كدا !
إمتي أستخدمه والأمثلة اللي بي shine فيها ؟
لو عايز تراقب متى يتم إضافة أو إزالة عناصر في الـ DOM. دا مفيد لما يكون عندك محتوى بيتحدث ديناميكياً بناءً على تفاعل المستخدم أو بيانات جديدة.
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.addedNodes.length > 0) {
console.log('Element added:', mutation.addedNodes[0]);
}
if (mutation.removedNodes.length > 0) {
console.log('Element removed:', mutation.removedNodes[0]);
}
});
});
لو عايز تراقب متى يتغير أي attribute في عنصر معين. دا مفيد لو عايز تتبع تغييرات معينة زي تغيير الـ class أو الـ style.
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes') {
console.log('Attribute changed:', mutation.attributeName);
}
});
});
لو عايز تراقب متى يتغير النص داخل عنصر معين. دا مفيد لو عندك محتوى بيتم تحديثه ديناميكياً وعايز تتأكد من تحديثه بشكل صحيح.

const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'characterData') {
console.log('Text changed:', mutation.target.data);
}
});
});

MutationObserver
بيكون أداة قوية ومهمة لما تحتاج تتبع التغييرات بدقة وكفاءة في الـ DOM، بس في نفس الوقت، ما بيستخدمش لما تكون التغييرات ممكن تتبعها بأحداث بسيطة زي scroll أو click أو input.
هنتكلم عن ال Proxies وتعال أفاجئك بسر بسيط
Vue 3
مبني على الـ Proxies بشكل أساسي. في الإصدار الثالث من Vue، تم استخدام الـ Proxy لتحسين الأداء والتفاعل مقارنةً بالإصدار الثاني اللي كان بيعتمد على Object.defineProperty.
فالمقال دا مش رفاهية لو متعرفش يعني إيه Proxy؟
الـ Proxies مش صعبة، بس الsyntax بتاعها ممكن يكون غريب شوية في البداية! يلا نكتشف مع بعض إيه هي، إزاي بتشتغل، وبعض الأمثلة العملية.

إيه هو Proxy؟
Proxy
في JavaScript هو object بيلف حوالين object تاني (بنقول عليه target) وبيترصد العمليات الأساسية اللي بتتعمل عليه زي الوصول للخواص(access propeties )، التعيين(set)، واستدعاء الfunctions عن طريق تحديد سلوك مخصص للعمليات دي، Proxies بتسمح للديفلوبرز بإنهم يعملوا تطبيقات ديناميكية ومرنة جداً.
ببساطة، Proxy هو Wrapper حوالين object عشان يديك قدرات متقدمة على الobjects.

الsyntax بص هتتوه وتحس الدنيا تقيلة وإنك مش فاهم بس ممكن تصبر لما توصل للكود وترجع تبص ع الsyntax هتفهم إي الtraps والحاجات الغريبة دي ، ف اصبر معايا للأخر بالله
إنشاء Proxy سهل ، دي الsyntax الأساسية:

const proxy = new Proxy(target, handler);

target:
الobject اللي الـ Proxy هيwrap له.
handler
الobject بيحتوي على traps (دوال) اللي بتحدد السلوك المخصص للعمليات المختلفة.

Traps
هي الfunctions اللي بنحددها في كائن الـ handler عشان نرصد العمليات. بعض الـ traps الشائعة تشمل:
get
بتتعامل مع property access
set
بتتعامل مع property assignment
has
بتتعامل مع operator ال in
الـ in بيستخدم عشان يتحقق إذا كان الobject بيحتوي على خاصية معينة ولا لأ.
يعني بيشوف إذا كانت الخاصية موجودة في الobject أو لا.
deleteProperty
بتتعامل مع حذف الخواص.
apply: بتتعامل مع استدعاء الدوال(function invocation).
construct
بتتعامل مع
new operator ال

تعال بقي واحدة واحدة نفك الألغاز دي
إنشاء Proxy بسيط
يلا نعمل Proxy بسيط عشان نسجل "property access" و ال "property assignment" لل object .
بص للصورة رقم 1
بصيت فهمت ؟ طيب مش فاهم برضه أقدر أستفيد من الproxies إزاي ؟

- ممكن نستخدمها لفرض قواعد
الـ validation على الـobjects
دا بيكون مفيد جداً لما بنتعامل مع user input أو API responses. بيفتح لينا طبقة جديدة من الـ validation!
مثال ع دا الصورة رقم 2

- ممكن نستخدمها لربط البيانات في الـ frameworks، بيسمح بالتحديث التلقائي للـ UI لما الـ underlying data تتغير. ودا اللي Vue بتعمله .

ولو عاوز مثال بسيط يوضحلك الدنيا بص ع صورة رقم 3

- ممكن تساعد في تتبع الـ property access والـ modifications، مفيدة جداً في الـ debugging والـ profiling. ليها استخدام كبير في application testing.

- برضو ممكن نستخدمها لإنشاء immutable objects، بحيث ما ينفعش تغير الـ properties بتاعتها بعد ما تتحدد.
مثال ع دا بص ع الصورة رقم 4

الخلاصة ، Proxies بتمثل أداة قوية ومميزة في عالم JavaScript. بتمكنك من التحكم في سلوك الـ objects بشكل ديناميكي ومرن من خلال اعتراض الـ fundamental operations زي property access، property assignment، و function invocation. سواء كنت عاوز تطبق validation rules، تتبع الـ modifications، إنشاء immutable objects، أو حتى تبني data binding في الـ frameworks، Proxies هتفتح قدامك أبواب جديدة في البرمجة وتعزز من إمكانيات الـ applications بتاعتك. أتمنى المقال دا يكون وضح لك قوة وإمكانيات Proxies

تقدر تتابعني هنا
https://whatsapp.com/channel/0029VaBfs40KAwEfBoG88Q2J
2👍1
1
الجانب المظلم لـ useState في React

تعال بقي أقولك علي 4 غلطات بشعة بتعملها وانت بتستخدم useState وهتخليك تشد ف شعرك لو لسه مبتدأ

1 - Forgetting to Consider the Previous State
بص كدا ع الكود في صورة 1
لما تشتغل بـ useState في React، لازم تأخد في الاعتبار أحدث حالة للٍstate لما تupdateها . الغلطة دي ممكن تؤدي unexpected behaviors، خصوصًا لما تتعامل مع تحديثات سريعة أو multiple state updates
في الكود اللي صورة 1 => incrementCounter بيحدث العداد بناءً على قيمته الحالية.
ده ممكن يبان بسيط لكنه هيسبب مشاكل
React ممكن تجمع عدة استدعاءات setCounter مع بعض، أو تحديثات حالة تانية ممكن تتداخل، وبالتالي الcounter مش هيتم تحديثه بشكل صحيح كل مرة ، دي ميزة في react إسمها batch
عشان متعملش renders كتير وتحسن البريفورمانس
عشان تتجنب المشكلة دي استخدم ال functional form من setCounter
النسخة دي بتاخد function كـ argument، وReact بتcall function دي بأحدث قيمة للحالة. ده بيضمن إنك دايمًا شغال بأحدث قيمة للstate


const incrementCounter = () => {
setCounter(prevCounter => prevCounter + 1); // بيحدث بشكل صحيح بناءً على أحدث حالة
};
2 - Neglecting State Immutability
في قاعدة مهمة أوي هتتعلمها ف بداية تعلمك ريأكت إسمها don't mutate the state
متلعبش في ال state ي حبيبي بس يا بابا ، إلا من خلال الsetState


const [profile, setProfile] = useState({ name: 'John', age: 30 });

const updateAge = () => {
profile.age = 31; // تغيير الحالة مباشرة
setProfile(profile);
};


الكود ده بيغير object profile مباشرة. التغييرات دي مش بتؤدي لإعادة الـ render ولكن بتحصل مشاكل من ورا حركة زي دي زي إيه ؟
الحالة دي، profile.age هيكون 31، لكن الـ UI هيظل يعرض 30 لأن React مش عارف إن فيه تغيير حصل لإن مفيش rerender حصل
لما بتغير الstate بشكل مباشر، ده بيصعب على React تتبع التغييرات، وده ممكن يؤدي لمشاكل في الأداء لأن React مش قادر يدير الـ render بشكل فعال.
لو فيه أجزاء تانية من الكود معتمدة على الحالة القديمة، التغييرات المفاجئة دي ممكن تؤدي لأخطاء أو تصرفات غريبة في التطبيق.

3: Misunderstanding Asynchronous Updates
تحديثات الstate في React باستخدام useState غير متزامنة (asynchronous). ده بيسبب لخبطة، خصوصًا لما يتم تحديث الحالة بسرعة ورا بعض. إنت كمبرمج ممكن تتوقع إن الحالة تتغير فورًا بعد استدعاء setState، لكن في الواقع، React بتجمع التحديثات دي علشان تحسن الأداء ، الpatching هتكلم عنه بالتفصيل قدام لا تقلق إستناه في مقالة رايقة :(

تعال نشوف مثال بيبين المشكلة دي بص ع الكود ف صورة رقم 2

في المثال ده، عايز يعدل count مرتين. لكن بسبب الpatching ، كل استدعاء لـ setCount بيتم بناءً على نفس الحالة الأولية، وبالتالي count بيزيد مرة واحدة بس.

علشان تتعامل مع الsetStateبشكل صحيح، استخدم ال (functional update) لـ setCount. ده بيضمن إن كل تحديث بيتم بناءً على أحدث حالة

const incrementCount = () => {
setCount(prevCount => prevCount + 1);
setCount(prevCount => prevCount + 1);
// دلوقتي كل تحديث بيتم بناءً على أحدث حالة
};



4- State for Derived Data
استخدام الstate لبيانات ممكن نشتقها من existing state تانية أو من الـ props
بص ع الكود في الصورة ال 3 كدا ، هل إنت شايف ال greeting state ليها لازمة ؟؟
greeting مش لازمة لأننا نقدر نشتقها مباشرة من name.





const GreetingComponent = ({ name }) => {
const greeting = Hello, ${name}; // مشتقة مباشرة من props

return (
<div>{greeting}</div>
);
};

export default GreetingComponent;



استخدام الـ useState هوك في React بشكل فعال مهم جداً لبناء تطبيقات موثوقة وكفء. لما تفهم وتتجنب الأخطاء الشائعة—زي إهمال الـ previous state، الـ state immutability mismanagement، تجاهل الـ asynchronous updates، وتجنب استخدام state مشتقة من الـ derived data—هتقدر تضمن سلوك سلس وقابل للتنبؤ.
1
1
JavaScript Web Workers
شايفك بتهرش في دماغك وبتسأل نفسك سؤال مهم
إزاي JavaScript بتشتغل بسنجل thread و Web Workers بتعمل Multi-threading؟
هجاوبك بالتفصيل في الأخر

لو بتدور على طريقة تخلي كود JavaScript بتاعك أسرع وأكثر كفاءة، Web Workers ممكن يكونوا أفضل صديق ليك! النهارده هنتكلم عن مفهوم جميل زي ما يكون عندك superhero Assistant لتطبيقات الويب بتاعتك
Web Workers إيه بقى دول؟
فكر في Web Workers كحاجة بتشتغل في الخلفية، بيعملوا مهام زي الحسابات المعقدة أو معالجة البيانات من غير ما يبطئوا الـ main thread بتاعك. ده معناه إن تطبيق الويب بتاعك يفضل سلس وسريع حتى لما تكون بتتعامل مع مهام تقيلة.
ليه تتعب نفسك مع Web Workers؟
JavaScript
بيشتغل بthread واحد (single-threaded)، يعني بيعمل حاجة واحدة في الوقت الواحد.
لما تشغل مهمة طويلة على الـ main thread، تطبيق الويب بتاعك ممكن يهنج أو ياخد وقت في التحميل، ويخلي المستخدمين يستنوا ويحسوا بالإحباط تخيل تفضل تضغط ع زرار ومفيش حاجة بتحصل !!!
Web Workers
بتيجي تنقذك بإنها تتعامل مع المهام دي على thread مختلف، فالتطبيق بتاعك يفضل مستجيب، والمستخدمين يبقوا مبسوطين من السرعة.
خلينا نشمر إيدينا ونخش ف الكود شوية!
هنقسم الموضوع لخطوات بسيطة علشان تفهم إزاي بيشتغل!
الخطوة الأولي => إنشاء سكريبت الـ Worker
أول حاجة، محتاجين ملف JavaScript منفصل لل workers بتوعنا. نسميه مثلاً worker.js أو أي اسم تفضله!
بص ع الكود في صورة واحد
في الكود ده، بنجهز الـ worker علشان يستقبل الرسائل باستخدام self.onmessage، ويعمل المهام التقيلة (زي حساب رقم Fibonacci)، وبعدين يبعت النتيجة باستخدام postMessage.

ممكن تقولي إستني ي عم هو ف إيه و إيه هو self؟ أو إيه هي postMessage و onmessage؟
Web Workers
بيشتغلوا في global context مختلف، مش الـ window اللي احنا عارفينه
بنسمي الglobal context الخاص ده self!
Web Workers
بيتواصلوا مع الـ main thread باستخدام الأحداث (events).
باستخدام الأحداث، يقدروا يبعتوا ويستقبلوا رسائل أو بيانات. في الكود، onmessage عادة بيستقبل رسائل أو بيانات من الـ main thread،
وpostMessage بيبعت البيانات المعالجة من الـ Web Worker لل main thread

الخطوة التانية إنشاء والتحدث مع الـ Worker
دلوقتي، هنشوف إزاي ننشئ Worker ونبعت رسائل/بيانات ليه من السكريبت الرئيسي بتاعنا ، مستني إيه بص ع الصورة رقم 2
هنا، بننشئ worker جديد، نبعت رسالة ليه باستخدام worker.postMessage
ونستلم النتائج باستخدام worker.onmessage
كمان بنتعامل مع أي أخطاء محتملة باستخدام worker.onerror
طب م دا برضه كلام حلو بس مش كفاية أنا عاوز أشوف سيناريوهات تفيدني واقعية
لو عندك array كبيرة جدا عاوز تعملها sort
خلينا نخلي Web Worker يتعامل مع الموضوع ده بص ع الكود في صورة 3

مثال تاني واقعي أكثر
عندك api بتعملها fecth وبتغيب ؟ هييجي واحد يقولي أنا شغال Asynchronous هقوله ماشي ي حبيبي ده مبيغيرش حقيقة إن fetch بيشتغل على الـ main thread حتى لو استخدمت async/await،
كمثال ع دا بص ع الصورة رقم 4

ال Best Practices عشان تستخدم ال Web Workers
Web Workers
معندهمش وصول مباشر للـ DOM، فخلي مهامهم مركزة.
دايماً ضيف error handling علشان تتجنب المشاكل.
معظمنا بيستخدم JavaScript في المتصفحات وعارفين إنها بتشتغل بسنجل ثريد، بس إزاي Web Workers بتعمل Multi-threading؟
JavaScript
مش بتحدد موديل معين للثريدينج، لكنها بتشتغل بسنجل ثريد في معظم المتصفحات. ده يعني إن الكود بيتنفذ في ثريد واحد، وكل العمليات بتتعمل واحدة واحدة.
معظم المتصفحات القديمة كانت بتشتغل بسنجل ثريد، بس دلوقتي المتصفحات زي Chrome، Firefox، بدأت تستخدم أكتر من ثريد عشان تحسن الأداء.
Web Workers مش جزء من JavaScript نفسها، لكنها ميزة في المتصفحات بنقدر نوصلها من خلال JavaScript.
الWorkers دي بتشتغل في ثريدات منفصلة، وده بيساعد على إننا نعمل عمليات تقيلة من غير ما نبطئ الـ main thread.
المتصفح هو اللي بيتولى إدارة الthreads. لما نعمل Worker، المتصفح بيكريت ثريد جديد ويشغل الكود بتاعه فيه.
الكود اللي بيشتغل في الـ Worker بيبقى منفصل عن الـ main thread، يعني مش بيتأثر بأي عمليات تانية شغالة في نفس الوقت يعني مش بنحتاج نقلق على موضوع الـ Memory model أو الـ concurrent access للمتغيرات.
الإتصال بين الـ main thread والـ Workers بيتم من خلال الرسائل (messages). ده بيسمح للـ Workers إنها تبعت وتستقبل بيانات من غير ما تأثر على الأداء العام.
2