medium을 요약하려고 한다. 문제가 되면 삭제하겠다.
- 결론적으로 React Hook은 Class Component가 Re-rendering 해주는 과정과 같다.
먼저 Class 형태의 Re-rendering 과정을 살펴보자.
-
OverReact에서 render는 Component 객체를 만들어서 render를 시키고 return 해준다.// 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() } } return { render, Component, } })()
- 이때, instance.render가 실행해주는 것은 instance의 render 메소드이다.
- this.setState에서 rendering을 트리거 해준다.
- 다음은 예시 코드이다.
-
setState가 instance에 액세스가 되므로, Component를 rendering을 다시 할 수 있음을 알 수 있다.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() } } 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 })) } 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}`) } } // instance -> return OverReact.render method const instance = render(ExtendedComponent) // 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
Hook에서는 어떻게 될까?
-
크게 달라질 부분이 없다.// extreamly simplified implementation function render(Component) { // ToDo // render the Component } function useState(initialState) { // ToDo // derive currentState let currentState function setState(newState) { // ToDo // update currentState with newState // rerender the component } return [currentState, setState] } OverReact = { render, useState, }
- setState 부분이 Component 함수에 접근할 수 있어야 하므로 OverReact의 render 함수를 trigger해주는 형태로 만들면 된다.
- useState가 여러개 호출되는 경우가 많기에 callId를 사용해 줄 것이다.
- 자세한 내용은 medium에서 확인이 가능하나 나는 제대로 이해하지 못했다.
- 다음은 예시 코드이다.
OverReact = (function () {
let context = {}
let callId = -1
function render(Component) {
context.Component = Component
const instance = Component()
instance.render()
callId = -1
delete instance.render
context.instance = instance
return context
}
function useState(initialState) {
if (!context) {
throw new Error("hooks can not be called with out a rendering context")
}
if (!context.hooks) {
context.hooks = []
}
callId = callId + 1
const hooks = context.hooks
const currentState = hooks[callId] ? hooks[callId] : initialState
hooks[callId] = currentState
const setState = (function () {
const currentCallId = callId
return function (newState) {
hooks[currentCallId] = newState
render(context.Component)
}
})()
return [currentState, setState]
}
return {
render,
useState,
}
})()
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,
}
}
const context = render(Component)
// rendered, counter: 0, name: foo
context.instance.plusOne()
// rendered, counter: 1, name: foo
context.instance.updateName("bar")
// rendered, counter: 1, name: bar
context.instance.plusOne()
// rendered, counter: 2, name: bar
context.instance.updateName("baz")
// rendered, counter: 2, name: baz
context.instance.plusOne()
// rendered, counter: 3, name: baz
- react에 있는 useState는 setState에서 OverReact의 render를 호출해준다.
- 그리고 OverReact는 Componenet의 Render를 호출해주면서 Re-Rendering이 된다.
'Web > React' 카테고리의 다른 글
[React] react-hooks/exahaustive-deps lint를 깔끔하게 지켜보자 (0) | 2022.03.28 |
---|---|
[React] Context API를 통한 전역 상태 관리 (with Typescript) (0) | 2022.02.16 |
[React LifeCycle] 리액트의 생명주기 (0) | 2022.02.01 |
[React Fiber Architecture] What is React-Fiber Architecture? (0) | 2022.01.31 |