একটি প্রতিক্রিয়া উপাদান কেন পুনরায় উপস্থাপন করছে তা ট্রেস করুন


156

রিব্যাক্টে কোনও উপাদানকে পুনরায় রেন্ডার করার কারণে ডিবাগ করার জন্য কি কোনও নিয়মতান্ত্রিক পন্থা রয়েছে? এটি কত সময় রেন্ডার করে তা দেখতে আমি একটি সাধারণ কনসোল.লগ () রেখেছি, তবে উপাদানটি আমার ক্ষেত্রে একাধিকবার (4 বার) রেন্ডার করছে কি তা নির্ধারণ করতে সমস্যা হচ্ছে। এমন কোনও সরঞ্জাম রয়েছে যা একটি টাইমলাইন এবং / অথবা সমস্ত উপাদান গাছের রেন্ডার এবং ক্রম দেখায়?


হতে পারে আপনি shouldComponentUpdateস্বয়ংক্রিয় উপাদান আপডেট অক্ষম করতে এবং তারপরে সেখান থেকে আপনার ট্রেস শুরু করতে পারেন। আরও তথ্য এখানে পাওয়া যাবে: facebook.github.io/react/docs/optimizing-performance.html
রেজা সদর

@ jpdelatorre এর উত্তর সঠিক। সাধারণভাবে, রিঅ্যাক্টের একটি শক্তি হ'ল আপনি কোডটি দেখে সহজেই ডেটা প্রবাহকে শৃঙ্খলাবদ্ধ করতে পারেন। প্রতিক্রিয়া DevTools এক্সটেনশন দিয়ে করতে পারে। এছাড়াও, আমার
রেডাক্স অ্যাডোনস

উত্তর:


253

আপনি যদি কোনও বাহ্যিক নির্ভরতা ছাড়াই একটি সংক্ষিপ্ত স্নিপেট চান তবে আমি এটি দরকারী বলে মনে করি

componentDidUpdate(prevProps, prevState) {
  Object.entries(this.props).forEach(([key, val]) =>
    prevProps[key] !== val && console.log(`Prop '${key}' changed`)
  );
  if (this.state) {
    Object.entries(this.state).forEach(([key, val]) =>
      prevState[key] !== val && console.log(`State '${key}' changed`)
    );
  }
}

ফাংশন উপাদানগুলির আপডেটগুলি ট্রেস করতে আমি এখানে একটি ছোট হুক ব্যবহার করি

function useTraceUpdate(props) {
  const prev = useRef(props);
  useEffect(() => {
    const changedProps = Object.entries(props).reduce((ps, [k, v]) => {
      if (prev.current[k] !== v) {
        ps[k] = [prev.current[k], v];
      }
      return ps;
    }, {});
    if (Object.keys(changedProps).length > 0) {
      console.log('Changed props:', changedProps);
    }
    prev.current = props;
  });
}

// Usage
function MyComponent(props) {
  useTraceUpdate(props);
  return <div>{props.children}</div>;
}

5
@ yarden.refaeli আমি ইফ ব্লক করার কোনও কারণ দেখতে পাচ্ছি না। সংক্ষিপ্ত এবং সংক্ষিপ্ত।
ইসহাক

এর পাশাপাশি, যদি আপনি দেখতে পান যে কোনও রাজ্যের অংশ আপডেট করা হচ্ছে এবং কোথায় বা কেন এটি স্পষ্ট নয় তবে আপনি setStateপদ্ধতিটি (শ্রেণির উপাদানটিতে) ওভাররাইড করতে পারেন setState(...args) { super.setState(...args) }এবং তারপরে আপনার ডিবাগারে একটি ব্রেকপয়েন্ট সেট করতে পারেন যা আপনি সক্ষম হবেন তখন রাষ্ট্রটি নির্ধারণ করে ফাংশনে ফিরে যেতে।
redbmk

আমি হুক ফাংশনটি কীভাবে ব্যবহার করব? useTraceUpdateআপনি যেমনটি লিখেছেন ঠিক তেমন সংজ্ঞা দেওয়ার পরে আমি কোথায় ফোন করব?
অভিশাপ

একটি ফাংশন উপাদানটিতে, আপনি এটি এটির মতো ব্যবহার করতে পারেন function MyComponent(props) { useTraceUpdate(props); }এবং যখনই প্রপস পরিবর্তন হয় তখন এটি লগ হবে
জ্যাকব রাস্ক

1
@ ডসনবি আপনার সম্ভবত সেই উপাদানটিতে কোনও রাজ্য নেই, তাই this.stateসংজ্ঞায়িত।
জ্যাকব রাস্ক

67

এখানে কিছু উদাহরণ রয়েছে যা একটি প্রতিক্রিয়া উপাদান পুনরায় রেন্ডার করবে।

  • মূল উপাদান রেন্ডার
  • this.setState()উপাদানটির মধ্যে কল করা হচ্ছে । এর ফলে, নিম্নলিখিত উপাদান জীবনচক্র পদ্ধতি আরম্ভ হবে shouldComponentUpdate>componentWillUpdate >render >componentDidUpdate
  • উপাদানগুলির পরিবর্তনসমূহ props। এই ইচ্ছার ট্রিগার componentWillReceiveProps> shouldComponentUpdate> componentWillUpdate> render> componentDidUpdate( connectপদ্ধতিreact-redux ট্রিগার এই যখন Redux দোকান প্রযোজ্য পরিবর্তন)
  • কলিং this.forceUpdateযা অনুরূপthis.setState

আপনার অভ্যন্তরের চেক প্রয়োগ করে shouldComponentUpdateএবং ফিরে এসে আপনি আপনার উপাদানটির রেন্ডার হ্রাস করতে পারেনfalse যদি প্রয়োজন হয় না তবে পারেন।

আর একটি উপায় হ'ল রাজ্যবিহীন উপাদানগুলি ব্যবহার করা React.PureComponent । খাঁটি এবং রাষ্ট্রবিহীন উপাদানগুলি কেবল তখনই পুনরায় রেন্ডার করে যখন এর প্রপসগুলিতে পরিবর্তন হয়।


6
নিতপিক: "স্টেটলেস" এর অর্থ এমন কোনও উপাদান যা রাষ্ট্র ব্যবহার করে না, শ্রেণি বাক্য গঠন বা ক্রিয়ামূলক সিনট্যাক্সের সাথে নির্ধারিত হোক না কেন। এছাড়াও, কার্যকরী উপাদানগুলি সর্বদা পুনরায় রেন্ডার করে। পরিবর্তনের উপর কেবল পুনরায় রেন্ডারিং প্রয়োগ করতে আপনাকে হয় ব্যবহার করতে হবে shouldComponentUpdateবা প্রসারিত React.PureComponentকরতে হবে।
মার্কেরিকসন

1
আপনি স্ট্যাটাসহীন / কার্যকরী উপাদান সম্পর্কে সর্বদা পুনরায় রেন্ডারগুলি সম্পর্কে সঠিক। আমার উত্তর আপডেট করবে।
jpdelatorre

আপনি কি পরিষ্কার করতে পারেন, কখন এবং কেন ক্রিয়ামূলক উপাদানগুলি সর্বদা পুনরায় রেন্ডার করে? আমি আমার অ্যাপ্লিকেশনটিতে বেশ কয়েকটি কার্যকরী উপাদান ব্যবহার করি।
জাসান

এমনকি আপনি যদি নিজের উপাদান তৈরির কার্যকরী উপায় ব্যবহার করেন যেমন const MyComponent = (props) => <h1>Hello {props.name}</h1>;(এটি একটি রাষ্ট্রবিহীন উপাদান)। এটি যখনই পিতামাতার উপাদান পুনরায় রেন্ডার করে তখন এটি পুনরায় রেন্ডার হবে।
jpdelatorre

2
এটি নিশ্চিতভাবে দুর্দান্ত উত্তর, তবে এটি আসল প্রশ্নের উত্তর দেয় না - কীভাবে পুনরায় রেন্ডার সৃষ্টি করেছিল তা কীভাবে চিহ্নিত করা যায়। জ্যাকব আর-এর উত্তর বাস্তব সমস্যার উত্তর দেওয়ার ক্ষেত্রে প্রতিশ্রুতিবদ্ধ দেখাচ্ছে।
সানুজ

10

@ jpdelatorre এর উত্তর সাধারণ কারণগুলিকে একটি প্রতিক্রিয়া উপাদান পুনরায় রেন্ডার করতে পারে তা হাইলাইট করার ক্ষেত্রে দুর্দান্ত।

আমি কেবল একটি উদাহরণের মধ্যে আরও গভীর ডুব দিতে চেয়েছিলাম: যখন প্রপস পরিবর্তন হয় । রিঅ্যাক্ট উপাদানকে পুনরায় রেন্ডার করতে সমস্যাজনিত সমস্যা সমাধান করা একটি সাধারণ সমস্যা এবং আমার অভিজ্ঞতায় অনেক সময় এই সমস্যাটি অনুসন্ধান করার সময় কোন প্রস পরিবর্তন হচ্ছে তা নির্ধারণের সাথে জড়িত

উপাদানগুলি পুনরায় রেন্ডার করুন প্রতিক্রিয়া করুন যখনই তারা নতুন প্রপস পান। তারা যেমন নতুন প্রসেস গ্রহণ করতে পারে:

<MyComponent prop1={currentPosition} prop2={myVariable} />

বা যদি MyComponentকোনও রিডুক্স স্টোরের সাথে সংযুক্ত থাকে :

function mapStateToProps (state) {
  return {
    prop3: state.data.get('savedName'),
    prop4: state.data.get('userCount')
  }
}

যে কোনো সময় এর মান prop1, prop2, prop3, অথবা prop4পরিবর্তন MyComponentপুনরায় প্রতিদান দেবেন। 4 টি প্রপসের সাহায্যে এটি শুরু করা খুব কঠিন নয় যে প্রপসটি console.log(this.props)সেই শুরুতে একটি স্থাপন করে কোন প্রপসগুলি পরিবর্তন হচ্ছেrender ব্লকের । তবে আরও জটিল উপাদান এবং আরও বেশি প্রপস সহ এই পদ্ধতিটি অযোগ্য।

কোন প্রোপ পরিবর্তনগুলি কোনও উপাদানকে পুনরায় রেন্ডার করিয়ে দিচ্ছে তা নির্ধারণ করতে এখানে একটি দরকারী পদ্ধতির ( সুবিধার জন্য লোড্যাশ ব্যবহার করে ):

componentWillReceiveProps (nextProps) {
  const changedProps = _.reduce(this.props, function (result, value, key) {
    return _.isEqual(value, nextProps[key])
      ? result
      : result.concat(key)
  }, [])
  console.log('changedProps: ', changedProps)
}

আপনার উপাদানটিতে এই স্নিপেট যুক্ত করা পুনরায় রেন্ডারকারীদের উদ্বেগজনিত অপরাধীকে প্রকাশ করতে সহায়তা করতে পারে এবং অনেক সময় এটি অপ্রয়োজনীয় ডেটা উপাদানগুলিতে নষ্ট করার বিষয়ে আলোকপাত করতে সহায়তা করে।


3
এটি এখন বলা হয় UNSAFE_componentWillReceiveProps(nextProps)এবং এটি অবহেলা করা হয়। "এই জীবনচক্রটির আগে নামকরণ করা হয়েছিল componentWillReceivePropsname নামটি 17 সংস্করণ অবধি চলতে থাকবে" " থেকে ডকুমেন্টেশন প্রতিক্রিয়া
এমিল বার্গারন 19

1
আপনি কম্পোনেন্টডিউডপেটেটের সাথে এটি অর্জন করতে পারেন, যা তাত্ক্ষণিকভাবে আরও ভাল, যেহেতু আপনি কেবল কোনও উপাদানটি কী কারণে আসলে আপডেট হয়েছিল তা সন্ধান করতে চাইছেন।
তীক্ষ্ণ দেখুন

5

অদ্ভুত কেউই উত্তরটি দেয়নি তবে আমি এটি খুব দরকারী বলে মনে করি, বিশেষত যেহেতু প্রপস পরিবর্তনগুলি প্রায় সবসময় গভীরভাবে বাসা বেঁধে থাকে।

হুক ফ্যানবয়:

import deep_diff from "deep-diff";
const withPropsChecker = WrappedComponent => {
  return props => {
    const prevProps = useRef(props);
    useEffect(() => {
      const diff = deep_diff.diff(prevProps.current, props);
      if (diff) {
        console.log(diff);
      }
      prevProps.current = props;
    });
    return <WrappedComponent {...props} />;
  };
};

"পুরাতন" -স্কুলের ফ্যানবয়:

import deep_diff from "deep-diff";
componentDidUpdate(prevProps, prevState) {
      const diff = deep_diff.diff(prevProps, this.props);
      if (diff) {
        console.log(diff);
      }
}

পিএস আমি এখনও এইচওসি (উচ্চতর অর্ডার উপাদান) ব্যবহার করতে পছন্দ করি কারণ কখনও কখনও আপনি শীর্ষে আপনার প্রপসটি তৈরি করে ফেলেছেন এবং জ্যাকব এর সমাধানটি ভাল মানায় না

দাবি অস্বীকার: প্যাকেজ মালিকের সাথে কোনও সম্পর্ক নেই। গভীরভাবে নেস্টেড বস্তুর মধ্যে পার্থক্য চিহ্নিত করার চেষ্টা করার জন্য প্রায় দশবার বার ক্লিক করা একটি ব্যথা।


4

এনপিএম-এ এইটির জন্য এখন একটি হুক রয়েছে:

https://www.npmjs.com/package/use-trace-update

(প্রকাশ, আমি এটি প্রকাশ করেছি) আপডেট: জ্যাকব রাসের কোডের উপর ভিত্তি করে তৈরি


14
এটি কার্যত একই কোড যা জ্যাকব পোস্ট করেছেন। ওকে সেখানে জমা দিতে পারত।
খ্রিস্টান আইভিসিভিক

2

হুকস এবং ক্রিয়ামূলক উপাদানগুলি ব্যবহার করে, কেবল প্রোপ পরিবর্তনই রেেন্ডার তৈরি করতে পারে। আমি যা ব্যবহার শুরু করেছি তা হ'ল একটি ম্যানুয়াল লগ। আমি আমাকে অনেক সাহায্য করেছি। আপনি এটি দরকারী দরকারী হতে পারে।

আমি এই অংশটি উপাদানটির ফাইলটিতে আটকান:

const keys = {};
const checkDep = (map, key, ref, extra) => {
  if (keys[key] === undefined) {
    keys[key] = {key: key};
    return;
  }
  const stored = map.current.get(keys[key]);

  if (stored === undefined) {
    map.current.set(keys[key], ref);
  } else if (ref !== stored) {
    console.log(
      'Ref ' + keys[key].key + ' changed',
      extra ?? '',
      JSON.stringify({stored}).substring(0, 45),
      JSON.stringify({now: ref}).substring(0, 45),
    );
    map.current.set(keys[key], ref);
  }
};

পদ্ধতির শুরুতে আমি একটি উইকম্যাপ রেফারেন্স রাখি:

const refs = useRef(new WeakMap());

তারপরে প্রতিটি "সন্দেহজনক" কল (প্রপস, হুকস) পরে আমি লিখি:

const example = useExampleHook();
checkDep(refs, 'example ', example);

1

উপরের উত্তরগুলি খুব সহায়ক, কেবল যদি কেউ যদি রেন্ডারটির কারণ সনাক্ত করার জন্য কোনও বিশেষ পদ্ধতির সন্ধান করে তবে আমি এই লাইব্রেরিটি রিডেক্স-লগারটি পেয়েছি খুব সহায়ক বলে মনে করেছি।

আপনি যা করতে পারেন তা হল লাইব্রেরি যুক্ত করা এবং রাষ্ট্রের মধ্যে পার্থক্য সক্ষম করা (এটি ডক্সে রয়েছে) যেমন:

const logger = createLogger({
    diff: true,
});

এবং স্টোরটিতে মিডলওয়্যার যুক্ত করুন।

তারপরে console.log()আপনি যে উপাদানটি পরীক্ষা করতে চান তার রেন্ডার ফাংশনে একটি রাখুন ।

তারপরে আপনি আপনার অ্যাপটি চালাতে পারেন এবং কনসোল লগগুলি পরীক্ষা করতে পারেন W যেখানেই কোনও লগ রয়েছে তার আগে আপনাকে রাষ্ট্রের মধ্যে পার্থক্য দেখাবে (nextProps and this.props)এবং আপনি ঠিক করতে পারেন যে সেখানে রেন্ডারটি সত্যই প্রয়োজন কিনা youএখানে চিত্র বর্ণনা লিখুন

এটি পৃথক কী সহ উপরের চিত্রের সাথেও মিলিত হবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.