리액트로 달력을 만들어 보려고 하는데 ref한 this.tableref.rows.current.length에서 null값이 뜨네요
디버그 해보니 current에 null값이 있구요.
어떻게 하면 저기에 값을 넣을 수 있을까요…?
클래스 컴포넌트 안에서 함수를 정의해서 문제인가요?
아니면 ref값을 못받아오는게 문제일까요…
해결책을 주시면 감사하겠습니다.
.
위 코드를 보아하니, this.state.today 프로퍼티를 수정하고 싶어하시는 거로 보입니다.
이런 코드에서는 크게 두 가지 문제점을 찾을 수 있습니다.
컴포넌트의 상태를 직접적으로 수정하는 문제.
컴포넌트의 상태를 직접 수정하는 행위는 React의 주된 무기 중 하나인 컴포넌트의 반응성(Reactivity)를 상실하는 행위입니다. 상태를 수정하셔야 할 때에는 Component.prototype.setState(a.k.a setState)를 사용하세요.
의미없는 mutable 한 바인딩을 만드는 문제.
위 코드에서 today 변수는 그 값을 수정하는 로직을 제외하면, 어떤 로직도 참조하지 않고 있습니다.
즉, 고립된 변수이지요. 이런 변수는 지우셔야 합니다(this.state.today와 today는 다른 바인딩입니다. today를 수정하신다고 해서 this.state.today가 수정되는 건 아니에요.).
God Object
God Object는 OOP에서 너무 많은 정보를 들고 있거나, 너무 많은 일을 하는 잘못된 객체를 가르키는 말 입니다.
보통 God Object는 코드(혹은 객체)의 결합도는 높이고 응집도는 낮춤으로서 유지보수는 물론 프로젝트 전반적으로 엄청난 피해를 입힙니다. 그래서 안티 패턴이라 불리며 기피되지요.
React가 OOP적인 프레임워크는 아니지만, Calendar 컴포넌트의 상태는 가히 God Object라 불러도 될 정도로 너무 많은(그리고 쓸모없는) 정보를 담고 있습니다. Date 객체는 전반적으로 날짜와 관련된 모든 정보와 정말 많은(거의 대부분의) 연산들을 가지고 있는 객체입니다. 다시말해, Date 객체는 날짜와 관련된 정보를 처리하는 일에 특화된 객체이지요. 그러나 작성자님은 이 객체를 Calendar 컴포넌트의 state에 가지고 있으심에도 불구하고 state에 year과 month라는, 불필요한 정보를 심지어 문자열로 저장해 두셨습니다(문자열은 날짜 계산을 위한 연산을 단 한 개도 가지고 있지 않습니다.). 말이 길어지긴 했는데, 결론은 간단합니다. 상태를 다음과 같이 바꾸시는 걸 권장해 드립니다.
state = {
currentDate = new Date();
}
DRY(Don’t Repeat Yourself)
올려주신 코드를 보면 prevCalendar와 nextCalendar 함수의 로직의 정말 많은 부분들이 겹쳐 있습니다.
이런 경우, 고차 함수 등을 이용해 추상화하시면 더 깔끔한 코드가 나옵니다.
Functional 하지 않은 setState는 위험합니다.
뒤에서 언급할 것이긴 합니다만… 작성하신 컴포넌트와 같이 setState가 한 Task에 여러 번 호출될 가능성이 있고, 수정되는 state의 프로퍼티가 겹치는 경우라면 setState의 로직이 분명 말썽을 일으킬 겁니다. functional setState is the future of react
자세한 설명을 하게 되면 이야기가 길어지니, 관련된 글을 첨부하는 것으로 이 문제는 마무리하겠습니다.
Ref을 남용하지 말아주세요.
만약 Ref을 공부하기 위해 사용하시는 거라면 다른 좋은 예제를 만드시는 걸 추천해 드리고,
그게 아니시라면 Ref을 잠시 치워두고 react스러운 방법을 찾아 고민해보시는 걸 추천해 드립니다.
render 메서드는 pure 하게 유지해 주세요.
올려주신 컴포넌트의 render 메서드는 prevCalendar 함수와 nextCalendar 함수를 매번 호출하고 있습니다. 기억하시나요? 저 두 함수는 컴포넌트의 상태를 바꾸는(impure 한) buildCalendar 메서드를 호출합니다.
디버깅을 위해서, reactivity를 위해서, 코드의 평화를 위해서, render 메서드는 pure 하게 작성하세요.