programing

얄팍한 비교는 반응에서 어떻게 작용합니까?

css3 2023. 3. 6. 21:22

얄팍한 비교는 반응에서 어떻게 작용합니까?

이 React 문서에는 다음과 같이 기술되어 있습니다.

shallCompare는 현재 소품 및 nextProps 객체뿐만 아니라 현재 상태 및 nextState 객체에 대해서도 얕은 균등성 검사를 수행합니다.

제가 이해할 수 없는 것은 오브젝트를 얄팍하게 비교할 경우 should ComponentUpdate 메서드는 항상 true를 반환한다는 것입니다.

우리는 주를 변형시켜서는 안 된다.

상태를 변환하지 않으면 비교 결과 항상 false가 반환되므로 should Component 업데이트는 항상 true가 반환됩니다.어떻게 동작하고 있는지, 퍼포먼스를 높이기 위해 어떻게 덮어쓸지 혼란스럽습니다.

얕은 비교는 동등함을 확인합니다.스칼라 값(숫자, 문자열)을 비교할 때는 그 값을 비교합니다.오브젝트를 비교할 때 오브젝트의 속성은 비교되지 않고 참조만 비교됩니다(예: "do they point to same object?").

다음 에 대해서 생각해볼까요?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);

얕은 비교는 변화를 감지하는 효율적인 방법입니다.데이터를 변환하지 않아야 합니다.

얄팍한 비교는 비교 대상 객체의 속성이 "===" 또는 엄격한 동등성을 사용하여 수행되고 속성에 대해 더 깊이 비교되지 않는 경우입니다.예를 들어,

// 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.teams2개의 오브젝트가 같으려면 같은 오브젝트를 가리켜야 합니다.됩니다.

// 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.

이번에는 새 객체와 이전 객체의 팀 속성이 동일한 객체를 가리키므로 모든 속성이 true로 반환되므로 엄밀한 비교를 위해 true가 반환됩니다.

// 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. 상태 객체가 깊이 중첩된 경우 성능에 큰 영향을 미치기 때문에 상세 비교는 무의미합니다.그러나 너무 중첩되지 않고 여전히 자세한 비교가 필요한 경우 should Component Update에서 구현하고 이것이 충분한지 확인합니다.
  2. 상태 오브젝트를 직접 변환할 수는 있지만 컴포넌트의 상태는 영향을 받지 않습니다.이는 컴포넌트 업데이트사이클 후크를 실행하는 setState 메서드플로우이기 때문입니다.컴포넌트의 라이프 사이클 훅을 의도적으로 회피하기 위해 상태 객체를 직접 갱신하는 경우에는 상태 객체가 아닌 단순한 변수 또는 객체를 사용하여 데이터를 저장해야 합니다.

얕은 비교는 문자열, 숫자 등 원시 유형의 경우 두 값이 동일한지 확인하고 객체의 경우 참조만 확인하는 방식으로 작동합니다.따라서 깊이 중첩된 개체를 얕게 비교할 경우 개체 내부의 값이 아닌 참조만 확인합니다.

리액트에는 얕은 비교에 대한 기존 설명도 있습니다.

shallCompare는 현재 소품 및 nextProps 객체뿐만 아니라 현재 상태 및 nextState 객체에 대해서도 얕은 균등성 검사를 수행합니다.

이는 비교 대상 객체의 키를 반복하여 각 객체의 키 값이 엄밀하게 동일하지 않은 경우 true를 반환함으로써 이루어집니다.

UPD: 현재 문서에서는 얕은 비교에 대해 설명합니다.

React 컴포넌트의 render() 함수가 동일한 소품 및 상태를 제공할 경우 React를 사용할 수 있습니다.Pure Component를 통해 성능을 향상시킬 수 있습니다.

React.PureComponent의 should ComponentUpdate()는 오브젝트를 얕게 비교합니다.여기에 복잡한 데이터 구조가 포함되어 있는 경우, 더 깊은 차이에 대한 잘못된 부정(false-negative)이 발생할 수 있습니다.단순한 소품 및 상태를 가질 것으로 예상되는 경우에만 Pure Component를 확장하거나 딥 데이터 구조가 변경되었음을 알고 있는 경우에는 forceUpdate()를 사용하십시오.

UPD2: 나는 화해 또한 얕은 비교 이해를 위한 중요한 주제라고 생각한다.

받아들여진 답변은 일부 사람들에게 다소 오해를 불러일으킬 수 있다.

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

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

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

이 문장은 특히 "사용자 이름을 변경했음을 알립니다.이 변경에도 불구하고 개체는 동일합니다.서로 참조가 완전히 일치합니다."

javascript에서 오브젝트로 다음을 수행할 경우:

const a = {name: "John"};
const b = a;

두 변수 중 하나를 변환하면 참조가 같기 때문에 두 변수가 모두 변경됩니다.은 항상하다.==, ===, Object.is()을(를) 상호 참조해 주세요(를를를를)

React의 경우 https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/shallowEqual.js의 간단한 비교 기능을 보여 줍니다.

/**
 * Performs equality by iterating through keys on an object and returning false
 * when any key has values which are not strictly equal between the arguments.
 * Returns true when the values of all keys are strictly equal.
 */
function shallowEqual(objA: mixed, objB: mixed): boolean {
  if (is(objA, objB)) {
    return true;
  }

  if (typeof objA !== 'object' || objA === null ||
      typeof objB !== 'object' || objB === null) {
    return false;
  }

  const keysA = Object.keys(objA);
  const keysB = Object.keys(objB);

  if (keysA.length !== keysB.length) {
    return false;
  }

  // Test for A's keys different from B.
  for (let i = 0; i < keysA.length; i++) {
    if (
      !hasOwnProperty.call(objB, keysA[i]) ||
      !is(objA[keysA[i]], objB[keysA[i]])
    ) {
      return false;
    }
  }

  return

Non-Primitive(개체)의 경우 다음 사항을 확인합니다.

  1. 번째 (「」를 사용).Object.is()에서 초단까지.
  2. 않는 경우 첫 의 각 한지 여부를 합니다(「」를 사용합니다).Object.is() )에서로 이동합니다2번입니다.이것은 첫 번째 키레벨에 대해서 실시합니다.객체에 값이 다른 객체의 키가 있는 경우 이 함수는 객체의 깊이에서 더 이상 동일성을 검사하지 않습니다.

알기까지 이 좀 .shallow compare ★★★★★★★★★★★★★★★★★」===특히 다음에 나오는 redux 문서를 읽을 때는 두 가지가 다릅니다.

단, 액션이 Redux 스토어에 디스패치되면 useSelector()는 셀렉터 결과가 마지막 결과와 다른 경우에만 강제로 재렌더를 실행합니다.v7.1.0-alpha.5 현재 기본 비교는 엄격한 === 참조 비교입니다.이는 mapState 콜 결과에 대한 얕은 등식 체크를 사용하여 재렌더링이 필요한지 여부를 판단하는 connect()와는 다릅니다.이것은 useSelector()를 사용하는 방법에 대해 몇 가지 영향을 미칩니다.

완전 대등한

단계별로 equal은 " " " " 입니다. " 입니다.===Javascript 언어(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality)에 의해 매우 일관되게 정의됩니다.

이 기능은 두 항목이 원시적인 경우 값을 기준으로 비교하고, 대상인 경우 참조를 통해 비교하는 것입니다.물론 두 개체의 유형이 다르면 절대 일치하지 않습니다.

얕은 비교

얄팍한 것은 아마 언어의 기본 기능은 아닐 겁니다.여기에서는, 몇개의 회답에 의해서, 실장의 몇개의 변화를 알 수 있었습니다.https://github.com/facebook/fbjs/blob/main/packages/fbjs/src/core/shallowEqual.js

그 아이디어는 두 항목이 원시적인 경우 가치별로 비교하는 것이다.하지만 원형이 아닌 경우에는 한 단계 낮춥니다.객체의 경우 키가 두 객체 간에 다를 경우 키가 동일하지 않다고 합니다.키 아래의 값이 다를 경우, 이 값도 동일하지 않다고 합니다.

요약

즉, 얄팍한 비교는 엄격한 동등성보다 더 많이 검사합니다.===특히 물체에 관해서는요.대충 보면,===너무 많은 추측을 하지 않는다.

위의 @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])
  )
}

위의 내용은 폴리필이 없는 탐색기에서 작동하지 않습니다.

예를 들어 구현이 있습니다.

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

이해하기 매우 간단합니다. 우선 순수 컴포넌트와 일반 컴포넌트를 이해해야 합니다. 컴포넌트가 소품이나 상태가 변화하고 있는 경우 컴포넌트를 다시 렌더링합니다.그렇지 않으면 일반 컴포넌트에서는 기본적으로 true여야 합니다.순수 성분에서는 diff 값에 따라 상태가 변화하는 시간만 해당됩니다.

그럼 얕은 컴포넌트 또는 얕은 컴포넌트는 무엇입니까?간단한 예를 들어보겠습니다.a = [1,2,3], b = [1,2,3],

a == b == > 얕은 것은 거짓, a == c == > 얕은 것은 참입니다.c에는 다른 값이 있습니다.

이제 이해하실 수 있을 것 같습니다. 일반 컴포넌트와 순수한 컴포넌트의 차이점이 마음에 드신다면 제 유튜브 채널 https://www.youtube.com/muosigmaclasses을 공유해서 구독하세요.

감사해요.

어떤 답변도 실제로 질문의 중요한 부분을 다루지 않았다고 생각합니다. 답변은 단지 얕은 비교가 무엇인지 설명할 뿐입니다(그들이 자바스크립트의 기본 얕은 비교를 의미하는지 여부).===또는==연산자 또는 리액트shallowCompare()기능)

당신의 질문에 답하기 위해, 지금까지의 리액트에 대한 저의 이해는 상태를 직접 변환하지 않음으로써 yes가 항상 true로 반환되므로 어떤 오브젝트를 통과하든 항상 재렌더가 발생한다고 믿게 합니다.setState가 건건 to로 넘어갔을 경우에도setState에 저장되어 것과

예:

리액트가 있다고 칩시다.현재 상태 및 기능이 있는 구성 요소:

this.state = {data: {num: 1}} // current state object
    
foo() { // something will cause this function to called, thus calling setState
       this.setState( {data: {num: 1}} ); // new state object
}

?setState그러나 플레인 리액트는 이 컴포넌트가 업데이트/재렌더되지 않아야 한다는 것을 인식할 만큼 스마트하지 않습니다.

는 자신의 해야 합니다.shouldComponentUpdate고려해야 한다고 생각되는 상태/요소에 대해 자신을 깊이 비교합니다.

이 질문에 대한 간단한 답변은 lucybain.com에서 이 기사를 참조하십시오.

언급URL : https://stackoverflow.com/questions/36084515/how-does-shallow-compare-work-in-react