Rayden Storm نشر 2 مارس 2021 أرسل تقرير نشر 2 مارس 2021 مرحبا لدي مكون أب يحتوي على منطق بسيط ويحتوي أيضا على مكون ابن ومشكلتي هي أنه عندما يعاد تشغيل المكون الاب يعاد تشغيل المكون الابن أيضا رغم أنه لم يتغير شئ في المكون الابن المكون الاب import { useState, useEffect } from 'react'; import Child from './Child'; export default function ParentComponent() { const [lang, setLang] = useState(''); const [framework, setFramwoek] = useState(''); const whichFamousFramwork = () => { switch (lang) { case 'javascript': return setFramwoek('react'); case 'python': return setFramwoek('django'); case 'php': return setFramwoek('laravel'); default: // eslint-disable-next-line no-unused-expressions 'django'; } }; useEffect(() => { let mounted = true; if (mounted) { whichFamousFramwork(); } return () => (mounted = false); }, [lang]); return ( <div dir="rtl"> <h1>اختر لغة وسنخبرك بأفضل فرايموورك</h1> <div> <button onClick={() => setLang('javascript')}>{'javascript'}</button> <button onClick={() => setLang('python')}>{'python'}</button> <button onClick={() => setLang('php')}>{'php'}</button> </div> {lang && ( <p> بالنسبة ل <span>{framework}</span>, {lang} هو أفضل فرايموورك </p> )} <Child /> </div> ); } المكون الابن import { useRef } from 'react'; function Child() { const renderCount = useRef(0); return ( <div> <p> لم يتغير شئ داخل child لكن اعيد تشغيله <span>{renderCount.current++} مرة</span> </p> </div> ); } export default Child; هل من طريقة لمعالجة الامر? اقتباس
0 Salah Eddin Beriani2 نشر 2 مارس 2021 أرسل تقرير نشر 2 مارس 2021 يمكنك استخدام react.memo في child لحل هذه المشكلة react.memo ستحرص أن المكون لن يعاد تشغيله ان لم يتغير فيه شئ import React, { useRef } from 'react'; function Child() { const renderCount = useRef(0); return ( <div> <p> لم يتغير شئ داخل child لكن اعيد تشغيله <span>{renderCount.current++} مرة</span> </p> </div> ); } export default React.memo(Child); اقتباس
0 أحمد حبنكة نشر 2 مارس 2021 أرسل تقرير نشر 2 مارس 2021 هنالك عدة أخطاء في كودك، اﻷولى أن هذا الكود: useEffect(() => { let mounted = true; if (mounted) { whichFamousFramwork(); } return () => (mounted = false); }, [lang]); مكافئ تماماً لهذا الكود: useEffect(() => { whichFamousFramwork(); }, [lang]); الثانية أن الـuseEffect وكذلك هذا السطر: const [framework, setFramwoek] = useState(''); لا داعي لهما، يمكن استبدال Parent بهذا الكود: export default function ParentComponent() { const [lang, setLang] = useState(''); let framework; switch (lang) { case 'javascript': framework = 'react'; case 'python': framework = 'django'; case 'php': framework = 'laravel'; default: // eslint-disable-next-line no-unused-expressions framework = 'django'; } return ( <div dir="rtl"> <h1>اختر لغة وسنخبرك بأفضل فرايموورك</h1> <div> <button onClick={() => setLang('javascript')}>javascript</button> <button onClick={() => setLang('python')}>python</button> <button onClick={() => setLang('php')}>php</button> </div> {lang && ( <p> بالنسبة ل <span>{framework}</span>, {lang} هو أفضل فرايموورك </p> )} <Child /> </div> ); } بالنسبة للـChild فإعادة تشغيله عند إعادة تشغيل المكون اﻷب أمر طبيعي ولا يجب تجنبه إلا إذا سبب ذلك مشاكل في performance حينها نلجأ ﻷمثال react.memo. إن كان إعادة تشغيل اﻻبن تسبب خطأً في logic فالمشكلة في اﻻبن وليس في اﻷب، في حالتك بالتحديد المشكلة في استخدام ref بهذه الطريقة ﻷنك تزيده مع كل استدعاء لتابع اﻻبن فمن الطبيعي أن يتغير اﻻبن عند عمل rerender له. المفضل في حالتك استعمال useState إما في اﻷب وتمرر للابن كـprops أو في اﻻبن وحينها يجب أن يكون هناك زر ما لتغيير state بدلاً من تغييره في جسم render حتى لا تتسبب في حلقة لا نهائية. بشكل عام لا يجوز تغيير state أو ref داخل render مباشرةً وإنما في حدث مثل onClick أو غيره ﻷن تغييره في render مباشرةً دائماً يسبب مشاكل مثل مشكلتك. اقتباس
السؤال
Rayden Storm
مرحبا لدي مكون أب يحتوي على منطق بسيط ويحتوي أيضا على مكون ابن ومشكلتي هي أنه عندما يعاد تشغيل المكون الاب يعاد تشغيل المكون الابن أيضا رغم أنه لم يتغير شئ في المكون الابن
المكون الاب
المكون الابن
هل من طريقة لمعالجة الامر?
2 أجوبة على هذا السؤال
Recommended Posts
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.