কিভাবে অগভীর কাজ প্রতিক্রিয়া মধ্যে তুলনা করে


97

ইন এই ডকুমেন্টেশন প্রতিক্রিয়া, এটি বলা হয় যে

shallowCompare বর্তমান প্রপস এবং নেক্সটপ্রপস অবজেক্টগুলির পাশাপাশি বর্তমান অবস্থা এবং নেক্সটস্টেট অবজেক্টগুলিতে অগভীর সমতা পরীক্ষা করে।

আমি যে জিনিসটি বুঝতে অক্ষম তা হ'ল এটি যদি অল্প মাত্রায় বস্তুর তুলনা করে তবে কম্পোনেন্ট আপডেট পদ্ধতিটি সর্বদা সত্য হিসাবে ফিরে আসবে

আমাদের রাজ্যগুলিকে পরিবর্তন করা উচিত নয়।

এবং যদি আমরা রাজ্যগুলিকে পরিবর্তন না করি তবে তুলনাটি সর্বদা মিথ্যা বলে প্রত্যাবর্তন করবে এবং তাই উচিত কম্পোনেন্ট আপডেটটি সর্বদা সত্য ফিরে আসবে। এটি কীভাবে কাজ করছে এবং পারফরম্যান্স বাড়ানোর জন্য আমরা কীভাবে এটি ওভাররাইড করব তা নিয়ে আমি বিভ্রান্ত am

উত্তর:


132

অগভীর তুলনা সমতার জন্য পরীক্ষা করে। স্কেলার মানগুলি (সংখ্যা, স্ট্রিং) তুলনা করার সময় এটি তাদের মানগুলির সাথে তুলনা করে। বস্তুর তুলনা করার সময়, এটি তাদের বৈশিষ্ট্যগুলির তুলনা করে না - কেবল তাদের উল্লেখগুলি তুলনা করা হয় (উদাহরণস্বরূপ "তারা কি একই বস্তুর দিকে নির্দেশ করে?)

আসুন আকৃতি নিম্নলিখিত বিবেচনা userবস্তুর

user = {
  name: "John",
  surname: "Doe"
}

উদাহরণ 1:

const user = this.state.user;
user.name = "Jane";

console.log(user === this.state.user); // true

লক্ষ্য করুন আপনি ব্যবহারকারীর নাম পরিবর্তন করেছেন। এমনকি এই পরিবর্তনের সাথে বস্তু সমান। তারা রেফারেন্স ঠিক একই।

উদাহরণ 2:

const user = clone(this.state.user);
console.log(user === this.state.user); // false

এখন, অবজেক্ট বৈশিষ্ট্যে কোনও পরিবর্তন ছাড়াই তারা সম্পূর্ণ আলাদা। আসল অবজেক্টটি ক্লোন করে আপনি বিভিন্ন রেফারেন্স সহ নতুন কপি তৈরি করেন।

ক্লোন ফাংশনটি এটি দেখতে (ES6 সিনট্যাক্স) হিসাবে দেখতে পারে

const clone = obj => Object.assign({}, ...obj);

অগভীর তুলনা পরিবর্তনগুলি সনাক্ত করার কার্যকর উপায়। এটি আশা করে যে আপনি ডেটা পরিবর্তন করবেন না।


সুতরাং যদি আমরা কোড লিখছি তবে আমাদের যদি স্কেলারের মান থাকে তবে তাদের কি আমাদের পরিবর্তন করা উচিত কারণ যদি আমরা তাদের ক্লোন করব, সাম্যতা পরীক্ষাটি মিথ্যা ফিরে আসবে?
অজয় গৌড়

30
@ অজয়গৌড় যদিও এই উত্তরটি আপনাকে জাভাস্ক্রিপ্টে কঠোর সমতা (===) বুঝতে সহায়তা করতে পারে, তবে এটি আপনাকে রিঅ্যাক্টে অগভীর কম্পিউটার () ফাংশন সম্পর্কে কিছুই জানায় না (আমি উত্তর দিয়েছি যে আপনার প্রশ্নের ভুল বোঝে)। অ্যালভো কম্পিয়ার () যা করে তা আসলে আপনার সরবরাহ করা দস্তাবেজটিতে: বস্তুর তুলনায় কীগুলির পুনরুক্তি করা এবং সত্য প্রত্যাবর্তন করা হয় যখন প্রতিটি বস্তুর কীগুলির মানগুলি সমানভাবে সমান হয় না। আপনি যদি এখনও এই ফাংশনটি বুঝতে না পারেন এবং কেন আপনার অবস্থা পরিবর্তন করতে হবে না, আমি আপনার জন্য একটি উত্তর লিখতে পারি।
সূর্যকান

7
এটা সত্য নয়. এটা দেখ. github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/…
ব্রাইট লি

4
এই উত্তরটি জেএসে সমতা (==) এবং কঠোর সমতা (===) অপারেটরগুলির মধ্যে পার্থক্য বর্ণনা করে। প্রশ্ন অগভীর তুলনা সম্পর্কে যা প্রতিক্রিয়াতে দুটি বস্তুর সমস্ত প্রপসের মধ্যে সমতা পরীক্ষা করে প্রয়োগ করা হয়।
মাতেও হ্রস্টনিক

@ সুনকান আপনি কি দয়া করে এর উপর একটি উত্তর লিখতে পারেন?
অজয় গৌর

35

অগভীর তুলনা হয় যখন তুলনামূলকভাবে বস্তুর বৈশিষ্ট্যগুলি "===" বা কঠোর সাম্য ব্যবহার করে সম্পন্ন করা হয় এবং বৈশিষ্ট্যের আরও গভীর তুলনা পরিচালনা করবে না। যেমন

// a simple implementation of the shallowCompare.
// only compares the first level properties and hence shallow.
// state updates(theoretically) if this function returns true.
function shallowCompare(newObj, prevObj){
    for (key in newObj){
        if(newObj[key] !== prevObj[key]) return true;
    }
    return false;
}
// 
var game_item = {
    game: "football",
    first_world_cup: "1930",
    teams: {
         North_America: 1,
         South_America: 4,
         Europe: 8 
    }
}
// Case 1:
// if this be the object passed to setState
var updated_game_item1 = {
    game: "football",
    first_world_cup: "1930",
    teams: {
         North_America: 1,
         South_America: 4,
         Europe: 8 
    }
}
shallowCompare(updated_game_item1, game_item); // true - meaning the state
                                               // will update.

যদিও উভয় বস্তু একইরূপে প্রদর্শিত হয়, game_item.teamsতবে একই রেফারেন্স নয় updated_game_item.teams। ২ টি অবজেক্ট একই হওয়ার জন্য তাদের একই জিনিসকে নির্দেশ করা উচিত। এইভাবে রাজ্যে এই ফলাফলগুলি আপডেট হতে মূল্যায়ন করা হচ্ছে

// Case 2:
// if this be the object passed to setState
var updated_game_item2 = {
    game: "football",
    first_world_cup: "1930",
    teams: game_item.teams
}
shallowCompare(updated_game_item2, game_item); // false - meaning the state
                                               // will not update.

এবার নতুন এবং পুরাতন অবজেক্টের টিমের সম্পত্তি একই বস্তুর দিকে নির্দেশ করার কারণে এই সম্পত্তিটির প্রত্যেকটি যথার্থ তুলনার জন্য সত্য ফিরে আসে।

// Case 3:
// if this be the object passed to setState
var updated_game_item3 = {
    first_world_cup: 1930
}
shallowCompare(updated_game_item3, game_item); // true - will update

updated_game_item3.first_world_cupসম্পত্তি ব্যর্থ 1930 যেমন কঠোর মূল্যায়ন একটি সংখ্যা থাকাকালীন game_item.first_world_cupএকটি পংক্তি। তুলনাটি আলগা হলে (==) এটি পাস হয়ে যেত। তবুও এর ফলে রাষ্ট্রীয় আপডেটও আসবে।

অতিরিক্ত নোট:

  1. গভীর তুলনা করা অর্থহীন কারণ এটি যদি রাষ্ট্রীয় বস্তুটি গভীরভাবে বাসা বাঁধে তবে তা পারফরম্যান্সকে উল্লেখযোগ্যভাবে প্রভাবিত করে। তবে যদি এটি খুব ঘৃণ্য না হয় এবং আপনার এখনও একটি গভীর তুলনা প্রয়োজন, তবে এটি প্রয়োগ করা উচিত কম্পোনেন্ট আপডেটে এবং এটি পর্যাপ্ত কিনা তা পরীক্ষা করুন।
  2. আপনি অবশ্যই রাষ্ট্রীয় অবজেক্টটি সরাসরি রূপান্তর করতে পারেন তবে উপাদানগুলির স্থিতি প্রভাবিত হবে না, কারণ সেটস্টেট পদ্ধতি প্রবাহে এটি প্রতিক্রিয়া করে উপাদান উপাদান চক্র হুক প্রয়োগ করে। আপনি যদি ইচ্ছাকৃতভাবে উপাদান লাইফ-চক্র হুকগুলি এড়ানোর জন্য রাষ্ট্রীয় অবজেক্টটি সরাসরি আপডেট করেন তবে সম্ভবত আপনার স্ট্যাটাসটি না করে ডেটা সংরক্ষণ করার জন্য একটি সাধারণ পরিবর্তনশীল বা অবজেক্ট ব্যবহার করা উচিত।

এর অর্থ এই নয় যে আমি যদি প্রপসের মাধ্যমে কোনও বস্তুটি পাস করি বা রাষ্ট্রের সাথে পরবর্তী অবস্থার তুলনা করি তবে উপাদানটি কখনই পুনরায় রেন্ডার করতে পারে না কারণ এমনকি যদি সেই বস্তুর বৈশিষ্ট্যগুলি পরিবর্তিত হয়, তবুও এটি একই বস্তুর দিকে নির্দেশ করবে, ফলস্বরূপ, ফলে মিথ্যা, এইভাবে, পুনরায় রেন্ডারিং না?
12:51

@ জাভাস্ক্রিপ্টিং - এজন্য আপনি যখন নিজের বস্তুগুলিকে পরিবর্তনের পরিবর্তে পরিবর্তিত করবেন তখন উদাহরণস্বরূপ অবজেক্ট.স্যাসাইন () ব্যবহার করে ক্লোন করতেন যাতে রেফারেন্সটি পরিবর্তিত হয় এবং উপাদানটি আপডেট হওয়ার প্রয়োজন হলে প্রতিক্রিয়াটি জানতে পারে।
ম্যাক_ডাব্লু

যদি prevObjএমন কী থাকে যা newObjনা থাকে তবে তুলনাটি ব্যর্থ হবে।
এমজেডেলার 13

@ এমজেডেলার - কারণ এটি "ইন ইন" নিউওবিজে পুনরুক্ত হয় এবং পূর্বোজেজে নয়। ব্রাউজার বিকাশকারী কনসোলের মতো কোড চালানোর চেষ্টা করুন। তবুও দয়া করে অগভীর এই বাস্তবায়নটিকে খুব গুরুত্বের সাথে তুলনা করবেন না, এটি কেবল ধারণাটি প্রদর্শনের জন্য
সুপি

অ্যারে সম্পর্কে কি?
জুয়ান দে লা ক্রুজ

27

অল্প কিছু স্ট্রিং, সংখ্যার মতো আদিম ধরণের ক্ষেত্রে সংখ্যার সমান কিনা তা পরীক্ষা করে কাজ করে এবং বস্তুর ক্ষেত্রে এটি কেবল রেফারেন্সটি পরীক্ষা করে । সুতরাং যদি আপনি অগভীর কোনও গভীর নেস্টেড বস্তুর তুলনা করেন তবে এটি কেবলমাত্র রেফারেন্সটি সেই বস্তুর অভ্যন্তরের মানগুলিতে পরীক্ষা করবে না।


11

এছাড়াও আছে উত্তরাধিকার ব্যাখ্যা প্রতিক্রিয়া তুলনা অগভীর এর:

shallowCompare বর্তমান প্রপস এবং নেক্সটপ্রপস অবজেক্টগুলির পাশাপাশি বর্তমান অবস্থা এবং নেক্সটস্টেট অবজেক্টগুলিতে অগভীর সমতা পরীক্ষা করে।

এটি প্রতিটি বস্তুর কীগুলির মানগুলি সমানভাবে সমান না হলে বস্তুগুলির তুলনা করা হচ্ছে এবং সত্যটি ফিরে আসার কীগুলিতে পুনরাবৃত্তি করে এটি করে।

ইউপিডি : বর্তমান ডকুমেন্টেশন অগভীর তুলনা সম্পর্কে বলে:

যদি আপনার রিঅ্যাক্ট উপাদানটির রেন্ডার () ফাংশন একই ফলাফলগুলিকে একই প্রসেস এবং স্থিতি দেয় তবে আপনি কিছু ক্ষেত্রে পারফরম্যান্স বৃদ্ধির জন্য React.PureComp घटक ব্যবহার করতে পারেন।

প্রতিক্রিয়া.পিউরকমম্পোনেন্টের উচিত কম্পোনেন্টস আপডেট () কেবলমাত্র অল্প মাত্রায় বস্তুর তুলনা করে। যদি এগুলিতে জটিল ডেটা স্ট্রাকচার থাকে তবে এটি গভীর পার্থক্যের জন্য মিথ্যা-নেতিবাচক উত্পাদন করতে পারে। আপনি যখন সহজ প্রপস এবং রাষ্ট্রের প্রত্যাশা করেন কেবল তখনই নির্ভেজাল অংশকে প্রসারিত করুন বা যখন আপনি জানবেন গভীর ডেটা স্ট্রাকচার পরিবর্তন হয়েছে তখন

ইউপিডি 2: আমি মনে করি যে অগভীর তুলনা বোঝার জন্য পুনর্মিলনটিও গুরুত্বপূর্ণ থিম।


এটি "মিথ্যা" হওয়া উচিত নাand returning true when the values
রাহুলগ

2

উপরে @supi দ্বারা অগভীর সমান স্নিপেট ( https://stackoverflow.com/a/51343585/800608 ) যদি নেই prevObjএমন কী থাকে যা ব্যর্থ newObjহয়। এখানে এমন একটি বাস্তবায়ন যা এটিকে আমলে নেওয়া উচিত:

const shallowEqual = (objA, objB) => {
  if (!objA || !objB) {
    return objA === objB
  }
  return !Boolean(
    Object
      .keys(Object.assign({}, objA, objB))
      .find((key) => objA[key] !== objB[key])
  )
}

নোট করুন যে উপরেরগুলি পলিফিল ছাড়া এক্সপ্লোরারে কাজ করে না।


দেখতে দুর্দান্ত লাগছে তবে এই ক্ষেত্রে দুটি উত্তর এনএর রিটার্ন মিথ্যা হয়ে গেছে যখন পূর্বের উত্তরে এটি সত্য।
স্পাডার শাট

0

উদাহরণ সহ একটি বাস্তবায়ন আছে।

const isObject = value => typeof value === 'object' && value !== null;

const compareObjects = (A, B) => {
  const keysA = Object.keys(A);
  const keysB = Object.keys(B);
 
  if (keysA.length !== keysB.length) {
    return false;
  }
 
  return !keysA.some(key => !B.hasOwnProperty(key) || A[key] !== B[key]);
};

const shallowEqual = (A, B) => {
  if (A === B) {
    return true;
  }
 
  if ([A, B].every(Number.isNaN)) {
    return true;
  }
  
  if (![A, B].every(isObject)) {
    return false;
  }
  
  return compareObjects(A, B);
};

const a = { field: 1 };
const b = { field: 2 };
const c = { field: { field: 1 } };
const d = { field: { field: 1 } };

console.log(shallowEqual(1, 1)); // true
console.log(shallowEqual(1, 2)); // false
console.log(shallowEqual(null, null)); // true
console.log(shallowEqual(NaN, NaN)); // true
console.log(shallowEqual([], [])); // true
console.log(shallowEqual([1], [2])); // false
console.log(shallowEqual({}, {})); // true
console.log(shallowEqual({}, a)); // false
console.log(shallowEqual(a, b)); // false
console.log(shallowEqual(a, c)); // false
console.log(shallowEqual(c, d)); // false

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