// **댄 : 함수형 컴포넌트의 리렌더링은 클래스형 컴포넌트의 리렌더링과 동일하다**
// react의 원리로 OverReact로 리렌더 구현
const { render, Component } = OverReact
class ExtendedComponent extends Component {
constructor(props) {
super(props)
this.state = {
counter: 0,
name: 'foo',
}
}
plusOne() {
const { state: previousState } = this
let { counter } = previousState
counter = counter + 1
this.setState(Object.assign(previousState, { counter }))
}
updateName(name) {
const { state: previousState } = this
this.setState(Object.assign(previousState, { name }))
}
render() {
const { counter, name } = this.state
console.log(`rendered, counter: ${counter}, name: ${name}`)
}
}
// initial render
render(ExtendedComponent)
// extreamly simplified implementation
OverReact = (function() {
function render(Component) {
const instance = new Component()
instance.render() // 해당 컴포넌트의 최초 렌더 메서드 실행
return instance
}
class Component {
constructor(props) {
this.props = props
}
setState(state) {
this.state = state
this.render() // setState 함수 내에서 해당 컴포넌트의 렌더함수를 실행
// 역주: Component를 extends하기 때문에 여기는 ExtendedComponent에서
// 직접 구현한 render()메소드가 됩니다
}
}
return {
render,
Component,
}
})() // 즉시 실행함수
const { render, Component } = OverReact
class ExtendedComponent extends Component {
constructor(props) {
super(props)
this.state = {
counter: 0,
name: 'foo',
}
}
plusOne() {
const { state: previousState } = this
let { counter } = previousState
counter = counter + 1
this.setState(Object.assign(previousState, { counter }))
// setState 실행시 해당 컴포넌트에 선언된 render 함수 실행
}
updateName(name) {
const { state: previousState } = this
this.setState(Object.assign(previousState, { name }))
// setState 실행시 해당 컴포넌트에 선언된 render 함수 실행
}
render() { // setState 실행시 애가 실행됨
const { counter, name } = this.state
console.log(`rendered, counter: ${counter}, name: ${name}`)
}
}
// 최초의 render
// 인스턴스는 OverReact.render method에 의해 반환 됩니다
const instance = render(ExtendedComponent)// OverReact 에 선언된 render 메서드
// rendered, counter: 0, name: foo
instance.plusOne()
// rendered, counter: 1, name: foo
instance.updateName('bar')
// rendered, counter: 1, name: bar
instance.plusOne()
// rendered, counter: 2, name: bar
instance.updateName('baz')
// rendered, counter: 2, name: baz
instance.plusOne()
// rendered, counter: 3, name: baz
closure
는 영구적인 메모리를 사용하지 않고 JavaScript 함수가 상태를 안전하게 유지할 수있는 유일한 방법글로벌 변수
에 상태를 유지하는 것은 안전하지 않으며 누구나 글로벌 변수
에 액세스 할 수 있으므로 결정적이지 않은 결과를 초래closure
는 유일한 옵션이 될 수 있음→ 클래스형 컴포넌트의 setState는 메서드니까 리렌더 로직을 넣을 수 있겠지만 hooks의 클로저가 어떻게 컴포넌트 리렌더의 트리거 역할을 할 수 있을까
// 위의 클래스형 OverReact를 함수형으로 구현
// 보통 함수형 컴포넌트처럼 jsx를 반환하는게 아닌 함수를 반환하는 것으로 구현해서 단순화
const { render, useState } = OverReact
function Component() {
const [counter, setCounter] = useState(0)
const [name, setName] = useState('foo')
function plusOne() {
setCounter(counter + 1)
}
function updateName(name) {
setName(name)
}
function render() {
console.log(`rendered, counter: ${counter}, name: ${name}`)
}
return {
render,
plusOne,
updateName,
}
}
// initial render
render(Component)