클래스형 컴포넌트의 리렌더링


[구현 예제]

// **댄 : 함수형 컴포넌트의 리렌더링은 클래스형 컴포넌트의 리렌더링과 동일하다**

// 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)

[OverReact 구현 및 setState의 리렌더 구현]

// 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

hooks & 함수형 컴포넌트의 리렌더링


[hook의 state는 클로저로 관리된다]

→ 클래스형 컴포넌트의 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)