inflearn logo
강의

Khóa học

Chia sẻ kiến thức

Học JS nâng cao qua giá gà rán

Tự triển khai useState

useState 직접 구현 부분에서 질문이 있습니다.

Đã giải quyết

47

taluee

2 câu hỏi đã được viết

1

setCount가 전역변수에 없으면 setCount is not defined; 오류가 발생합니다.
Codex가 Counter()는 문자열을 반환하고 setCount는 Counter의 지역변수라서 브라우저가 setCount를 전역에서 찾기 때문에 나타나는 오류라고 합니다. <--이부분이 어렵습니다.
아래처럼 변경하거나 addEventListener의 콜백으로 구현하라고 하네요.

const states = [];
    let cursor = 0;
    let setCount;

    function useState(initialValue) {
      const index = cursor;
      cursor++;

      if (states[index] === undefined) {
        states[index] = initialValue;
      }

      const setState = (newValue) => {
        states[index] = newValue;
        cursor = 0;
        render();
      };

      return [states[index], setState];
    }

    function Counter() {
      const [count, _setCount] = useState(0);
      setCount = _setCount;

      return `<button onClick="setCount(${count + 1})">${count}</button>`;
    }

    function render() {
      const root = document.querySelector("#root");
      cursor = 0;
      root.innerHTML = Counter();
    }

    render();

 

javascript 웹앱 함수형-프로그래밍 es6 객체지향 react.js vanilla-javascript

Câu trả lời 1

1

potatosam

안녕하세요! 질문 주셔서 감사합니다 :)

헷갈릴 수 있는 지점을 짚어주셔서 감사합니다.

먼저 해당 예제는 useState의 내부 아이디어를 가장 단순하게 보여주기 위한 개념 설명용 수도코드에 가까운 예제였습니다.
즉, “상태를 외부에 저장하고, setter가 상태를 바꾼 뒤 다시 render를 호출한다”는 흐름을 보여주는 데 초점을 둔 코드입니다.

다만 말씀해주신 것처럼, 이 코드를 브라우저에서 그대로 실행하면 setCount is not defined 오류가 발생할 수 있습니다.

문제는 이 부분입니다.


return `<button onclick="setCount(${count + 1})">${count}</button>`;

onclick="setCount(...)"는 HTML 문자열 안에 들어간 인라인 이벤트 핸들러입니다.

innerHTML로 DOM에 들어간 뒤 버튼을 클릭하면, 브라우저가 이 문자열을 자바스크립트 코드처럼 실행합니다.

이때 setCountCounter 함수 내부의 지역 변수로 찾는 것이 아니라, 전역(window) 스코프에서 찾게 됩니다.

그런데 setCount는 아래처럼 Counter 함수 안에서 만들어진 지역 변수입니다.

function Counter() {
  const [count, setCount] = useState(0);
}

그래서 클릭 시점에 브라우저가 window.setCount를 찾다 못 찾아 setCount is not defined 오류가 발생합니다.

해결 방법은 말씀 주신 것처럼 크게 두 가지입니다.

  1. setCount를 바깥 스코프에 선언해서 전역에서 접근 가능하게 만들기

  2. addEventListener로 이벤트 핸들러를 직접 연결하기



인라인 문자열 핸들러의 전역 스코프 문제를 피할 수 있고, 이벤트 콜백이 setCount를 클로저로 기억하기 때문에 addEventListener방식을 이용하는게 더 자연스러워 보입니다. ㅎㅎ

예를 들면 다음처럼 바꿀 수 있습니다.

// 전역 변수로 상태 저장 시도
let _state;

function useState(initialValue) {
  if (_state === undefined) {
    _state = initialValue;
  }

  const setState = (newValue) => {
    _state = newValue;
    render();
  };

  return [_state, setState];
}

function Counter() {
  const [count, setCount] = useState(0);

  const root = document.querySelector("#root");

  root.innerHTML = `<button id="btn">${count}</button>`;

  root.querySelector("#btn").addEventListener("click", () => {
    setCount(count + 1);
  });
}

function render() {
  Counter();
}

render();

개념 설명을 위해 단순화하다 보니, 실행 환경의 스코프 문제를 고려하지 못했네요 ㅠㅠ

강의 자료도 addEventListener 방식으로 보완하여 업로드하였습니다.(다시 다운로드 부탁드립니다!)

좋은 질문 주셔서 감사합니다. :)

소스코드 제공여부

0

10

2

선생님 공유해주신 핸드북에 링크가 몇개 잘못되었어요

0

13

2

62강 실습자료가 잘못되었습니다.

0

13

1

코드 자료는 없는걸까요?

0

21

2

기본 파일 구조

0

22

2

강의 화면이 안나와요

0

29

0

강의 목표

0

33

1

중급 과정 학습 중 복습과 진도 진행의 우선순위에 대해 질문드립니다

0

34

1

빠져나오기 위해서 System.in을 닫는다는게 무슨 의민가요??

0

30

1

supabase 인증페이지로 넘어가지 않습니다

0

56

2

강의 노트 위주로 학습

0

34

1

문제2번

0

41

1

claude 설치화면과 코딩내용미 표시 문의

0

62

2

쿠키 생성 관련

0

64

3

클로드 코드 설치 후 실행이 되지 않습니다

0

52

1

클로드 코드 실행 시 반복적으로 출력되는 메세지가 있습니다

0

60

2

JWT auth error invalid token

0

59

2

43강 강의내용 질문입니다.

0

52

1

경력기술서는 어떤 방향이 좋을까요?

0

52

2

강의를 듣다보니 궁금한 부분이 있습니다.

0

63

2

중복 코드와 유지보수성 사이에서 어떤 기준으로 리팩토링해야 할지 궁금합니다

0

35

1

static 변수를 호출할때 인스턴스변수 호출하듯이 호출해도 되나요?

0

50

1

AI에게 권한 부여하기

0

60

2

학습을 하고 블로그에 정리를 해도 괜찮을까요?

1

46

1