React 갈고리 의존 항목과 오래된 클립

우리가 inreact에 대해 자신감을 가지게 된 후에 그것의 의존성을 이해하는 것도 매우 중요하다.
이 글에서 우리는 갈고리의 의존수 그룹을 깊이 있게 연구할 것이다.
예전과 같이 자바스크립트 예시부터 시작합시다.출력을 보기 전에 무엇을 기록할지 추측해 보십시오.
function App(count) {
  console.log('Counter initialized with ' + count);
  return function print() {
    console.log(++count);
  };
}

let print = App(1);
print();
print();
print();

print = App(5);
print();
print();
위의 함수는 JavaScript에서 패키지를 닫는 간단한 예입니다.콘솔 출력은 다음과 같습니다.
Counter initialized with 1 
2
3
4
Counter initialized with 5 
6
7
만약 네가 얻을 수 있다면 정말 좋겠다.나는 무슨 일이 일어났는지 계속 설명할 것이다.App 함수는 print라는 다른 함수를 되돌려 App를 고급 함수로 만들었다.

Any function that returns another function or that takes a function as argument is called as Higher order function.


function App(count) {
  console.log('Counter initialized with ' + count);
  return function print() {
    console.log(++count);
  };
}
되돌아오는 함수 print 는 외부 작용역에서 오는 변수 count 를 닫습니다.이런 폐쇄를 폐쇄라고 부른다.
함수의 이름을 혼동하지 마세요.예컨대 이름이 꼭 똑같은 것은 아니다
function App(count) {
  console.log('Counter initialized with ' + count);
  return function increment() {
    console.log(++count);
  };
}

let someRandomName = App(1);
someRandomName(); //logs 2
여기서 응용 프로그램은 함수increment를 되돌려주고 변수someRandomName에 분배합니다.
"클러치"를 정의하려면

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. ~ MDN


예?이것은 보기에 간단한 정의 같지 않다, 그렇지?
알았어, MDN은 여기서 별로 도움이 안 돼. W3Schools가 뭐라고 했는지 보자.

A closure is a function having access to the parent scope, even after the parent function has closed. ~ W3Schools


우리가 App 함수를 호출할 때, 우리는 print 함수를 보답으로 받는다.
let print = App(1);
App 함수는 계수를 1로 설정하고 print로 되돌려줍니다. 이것은 계수를 증가시키고 기록할 뿐입니다.따라서 호출print할 때마다 계수가 증가하고 인쇄됩니다.
만약 우리가 클립을 사용하는 논리를 작성할 때 조심하지 않는다면, 우리는... 이라는 함정에 빠질 수도 있다.

낡은 봉투


낡은 클러치가 무엇인지 이해하기 위해서, 우리는 같은 예로 그것을 더욱 수정할 것이다.
이 코드를 보고 컨트롤러가 무엇을 로그인할지 알아맞혀 보세요.
function App() {

  let count = 0;

  function increment() {
    count = count + 1;
  }

  let message = `Count is ${count}`;

  function log() {
    console.log(message);
  }

  return [increment, log];
}

let [increment, log] = App();
increment();
increment();
increment();
log();
그것을 분해하려면,
  • 응용 프로그램에는 두 개의 변수countmessage가 있습니다.
  • 우리는 두 함수incrementlog를 되돌려준다.
  • 명칭에 따라 increment 우리의 countlog는 기록message에 불과하다.
  • 출력을 추측해 보세요.내가 너에게 생각할 공간을 좀 주겠다.
    .
    .
    .
    .
    .
    .
    .
    .
    경고!🚨 파괴자🚨 앞으로
    .
    .
    .
    .
    .
    .
    .
    .
    출력
    Count is 0
    
    오, 우리는 계수를 늘리지 않았습니까?
    콘솔에서 기능 확인
    function App() {
    
      let count = 0;
    
      function increment() {
        count = count + 1;
        console.log(count);
      }
    
      let message = `Count is ${count}`;
    
      function log() {
        console.log(message);
      }
    
      return [increment, log];
    }
    
    let [increment, log] = App();
    increment();
    increment();
    increment();
    log();
    
    이번에는 출력이
    1
    2
    3
    Count is 0
    
    네, 우리는 increment의 어법 범위 중count을 늘리고 있습니다.그러나 문제는incrementmessage에 있다.
    우리의 log 함수는 log 변수를 포획하고 보존했다.따라서 계수를 늘릴 때message는 업데이트되지 않으며, 우리message는 메시지'count is 0'을 되돌려줍니다.
    이 오래된 클립을 복구하려면, 우리는 메시지를 log로 이동할 수 있다
    function App() {
    
      let count = 0;
    
      function increment() {
        count = count + 1;
        console.log(count);
      }
    
      function log() {
        let message = `Count is ${count}`;
        console.log(message);
      }
    
      return [increment, log];
    }
    
    let [increment, log] = App();
    increment();
    increment();
    increment();
    log();
    
    집행하면 결과가 나오고,
    1
    2
    3
    Count is 3 
    
    말 그대로 Stale closure는 외부 범위에서 업데이트된 값을 포획할 수 없고, 오래된 값을 얻을 수 없다는 뜻이다.
    은마르코프 모형.그렇다면 이 케케묵은 결말은 리액트에 어떤 역할을 할까?

    갈고리는 단지 가방을 닫는 것에 불과하다!


    위에서 본 JS 예시를 리얼리티 세계로 가져가자.
    function App() {
      const [count, setCount] = React.useState(0);
    
      let message = `Count is ${count}`;
    
      React.useEffect(() => {
        if (count === 3) {
          console.log(message);
        }
      }, []);
    
      return (
        <div className="App">
          <h1>{count}</h1>
          <button
            onClick={() => {
              setCount((c) => c + 1);
            }}
          >
            Increment
          </button>
        </div>
      );
    }
    
    log 단추를 세 번 눌렀을 때, 우리는 로그에 '계수는 3' 을 표시해야 한다.
    유감스럽게도 우리는 어떤 사건도 기록하지 않았다!!!
    그러나 이것은 우리 JS세계에서 예시한 완전 복제품이 아니다. 관건적인 차이점은 우리의 React세계Increment가 확실히 갱신되었지만 우리message는 갱신 소식을 포착하지 못했다는 것이다.
    이 오래된 패키지 폐쇄 문제를 해결하려면 useEffectcount를 의존항수로 동시에 지정해야 한다.
    function App() {
      const [count, setCount] = React.useState(0);
    
      let message = `Count is ${count}`;
    
      React.useEffect(() => {
        if (count === 3) {
          console.log(message);
        }
      }, [count, message]);
    
      return (
        <div className="App">
          <h1>{count}</h1>
          <button
            onClick={() => {
              setCount((c) => c + 1);
            }}
          >
            Increment
          </button>
        </div>
      );
    }
    
    주의 - 이것은 단지 인위적인 예일 뿐입니다. 그 중 어느 의존항도 무시할 수 있습니다. 왜냐하면 둘 다 관련이 있기 때문입니다.message가 업데이트되었으면 count가 업데이트되었으며 그 중 하나만 지정하면 예상 출력을 얻을 수 있습니다.
    우리의 예에서 일은 매우 간단하다. 우리가 갈고리에서 작성한 논리는 진정한 부작용이 아니지만, 만약 우리가 데이터를 위해 논리와 기타 진정한 부작용을 얻기 시작한다면 갈고리는 점점 복잡해질 것이다
    우리가 확보해야 할 일은,

    All of our dependencies for hooks must be specified in the dependency array and, we should not lie to React about dependencies


    내가 말한 바와 같이 현실 세계의 응용 프로그램에서 클립은 일을 매우 복잡하게 하기 때문에 갈고리의 의존항을 무시하기 쉽다.
    내 경험에 의하면 만약에 우리가 의존항을 지정하지 않았고 테스트 과정에서 포획되지 않았다면 그것은 결국 버그를 초래할 것이다. 이를 복원하기 위해 우리는 처음부터 전체 논리를 다시 작성해야 할 것이다!!
    이것은 큰 문제다🚫 아니오.🚫 모든 대가를 아끼지 않고 피해야 한다.근데 어떻게 하지?

    ESLint 플러그인


    리액션팀은 갈고리를 사용할 때 발생할 수 있는 모든 오류를 포착하기 위해 message라는 ESLint 플러그인을 작성했습니다.
    따라서 의존 항목을 놓쳤을 때, 만약 당신이 이것을 준비했다면, 그것은 당신에게 가능한 결과를 경고할 것이다.
    최신create react 프로그램을 사용한다면, 이 프로그램은 상자를 열면 바로 사용할 수 있습니다 ((((eslint-plugin-react-hooks > = 3.0)
    아래 그림에서 보듯이 우리가 위반eslint plugin react hooks할 때 우리는 우리가 무엇을 잘못했는지 보여주는 좋은 경고를 받을 것이다.
    rules of hooks
    위의 그림은 React Hook React를 읽는 ESLint 오류를 보여 줍니다.useEffect에 의존 항목이 없습니다: "계수"와 "메시지".그것들을 포함하든지, 의존 항목의 그룹을 삭제하든지.
    그것은 심지어 클릭만 하면 의존성 문제를 해결할 수 있다.
    유행이 지난 폐쇄 문제는 react-scripts에 영향을 미칠 뿐만 아니라 다른 갈고리에서도 같은 문제를 만날 수 있다는 것을 명심하세요. 예를 들어 useEffectuseMemo.
    Eslint 플러그인은 모든 React 갈고리와 함께 작동하며 사용자 정의 갈고리에서 실행되도록 설정할 수 있습니다.의존성 문제를 일깨워주는 것 외에 갈고리의 모든 규칙을 검사할 수 있으니 잘 이용하세요!
    다시 실행,

    🚫 Don't Lie to React about Dependencies and 🚫 Don't disable this ESLint rule 🤷🏾‍♂️


    감사합니다:
  • Getting Closure on Hooks by Shawn Wang
  • Be Aware of Stale Closures when Using React Hooks
  • A Complete Guide to useEffect
  • 5 Tips to Help You Avoid React Hooks Pitfalls
  • 좋은 웹페이지 즐겨찾기