
사내 레거시 코드를 개선하던 중 발생한 트러블 슈팅 내용입니다.
B2B 페이지의 상품 등록 및 수정 페이지를 리팩토링하면서 발생.
ProductForm의 로직과 UI를 분리하기 위해 UI를 컴포넌트 단위로 수정했습니다.
UI 컴포넌트에 props로 state를 변경하는 setProduct라는 함수를 Container에서 넘겨줍니다.
UI 컴포넌트에서는 받은 props를 사용할 때 아래 사진과 같은 에러 발생 !!

JS에서 this는 함수를 호출하는 방식에 따라 그 값이 결정됩니다. 객체의 메서드로 함수를 호출하면, this는 그 객체를 가리킵니다. 하지만, 단순히 함수로 호출하면, this는 전역 객체(브라우저에서는 window, Node.js에서는 global)를 가리키거나, 엄격 모드('use strict')에서는 undefined가 됩니다.
JS 클래스 컴포넌트 내의 메서드는 기본적으로 그 컴포넌트 인스턴스에 바인딩되지 않습니다. 따라서, 컴포넌트의 메서드를 다른 컴포넌트의 prop으로 전달하거나, 이벤트 핸들러로 설정할 때, 그 메서드 내부에서 this를 사용하면, this는 컴포넌트 인스턴스를 가리키지 않게 됩니다. 이는 this.state나 this.setState 같은 컴포넌트의 state에 접근하려 할 때 문제를 일으킵니다.
이 문제를 해결하기 위한 방법 중 하나는 생성자(constructor) 내에서 메서드를 컴포넌트 인스턴스에 명시적으로 바인딩하는 것입니다. 이를 통해, 메서드가 어디서 호출되든 간에 this가 항상 해당 컴포넌트 인스턴스를 가리키도록 할 수 있습니다.
constructor(props) {
super(props);
this.setProduct = this.setProduct.bind(this);
}
이 코드는 setProduct 메서드 내의 this가 항상 해당 컴포넌트 인스턴스를 가리키도록 보장합니다. 그래서 this.state나 this.setState와 같은 state 관련 작업을 안전하게 수행할 수 있게 됩니다.
클래스 문법을 사용하여 메서드를 화살표 함수로 선언하는 것은 this가 인스턴스를 가리키게 하는 또 다른 방법입니다. 이 방식을 사용하면, 생성자에서 메서드를 바인딩할 필요가 없습니다.
setProduct = () => {
// 이곳에서의 this는 컴포넌트 인스턴스를 가리킵니다.
}
이 방법은 코드를 좀 더 간결하게 만들어주며, 바인딩을 잊어버려서 발생할 수 있는 버그를 예방해 줍니다.
현재는
setProduct를 사용하지 않고productInput컴포넌트를 활용하는 방식으로 수정했습니다.