اذهب إلى المحتوى
  • 0

مشكلة اعادة تشغيل المكونات الابناء في react

Rayden Storm

السؤال

مرحبا لدي مكون أب يحتوي على منطق بسيط ويحتوي أيضا على مكون ابن ومشكلتي هي أنه عندما يعاد تشغيل المكون الاب يعاد تشغيل المكون الابن أيضا رغم أنه لم يتغير شئ في المكون الابن 

603de0ff74cee_Peek2021-03-0207-53.gif.55264b393ecbdb0bcf5765b09d35d75e.gif

المكون الاب

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;

هل من طريقة لمعالجة الامر?

رابط هذا التعليق
شارك على الشبكات الإجتماعية

Recommended Posts

  • 0

يمكنك استخدام 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);

603de2b9cdd0b_Peek2021-03-0208-00.gif.83932036a2857d6e35922ce82414c5db.gif

رابط هذا التعليق
شارك على الشبكات الإجتماعية

  • 0

هنالك عدة أخطاء في كودك، اﻷولى أن هذا الكود:

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 مباشرةً دائماً يسبب مشاكل مثل مشكلتك.

رابط هذا التعليق
شارك على الشبكات الإجتماعية

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...