컴포넌트와 상태관리

나혜수·2023년 2월 8일
0

자바스크립트 실전

목록 보기
1/19

SSR, CSR

브라우저와 Javascript가 발전하는 과정에서, 브라우저(클라이언트) 단에서 렌더링을 하고 서버에서는 브라우저 렌더링에 필요한 데이터만 제공하는 형태로 기술이 변화했다. 직접적으로 DOM을 다루는 행위가 급격히 감소하고, 상태(State)를 기준으로 DOM을 렌더링 하는 형태로 발전한 것이다. 이러한 과정에서 Client-Side Rendering, 상태 관리라는 개념이 생겼다.

state - setState - render

간단한게 setState를 통해 state를 기반으로 render 해주는 코드를 만들어보자.

  • state가 변경되면 render를 실행한다.
  • statesetState 로만 변경해야 한다.

위의 규칙을 지켜 코드를 작성하면 브라우저 출력되는 내용은 state에 종속된다. 즉, DOM을 직접적으로 다룰 필요가 없다.

<div id="app"></div>
<script>
const $app = document.querySelector('#app'); 
// $변수는 보통 shadow dom host 역할을 하는 요소를 나타낼 때 사용합니다. 

/* 초기상태 */
let state = {
  items: ['item1', 'item2', 'item3', 'item4']
}

const render = () => {
  const { items } = state; // 구조 분해 문법입니다.
  $app.innerHTML = `
    <ul>
      ${items.map(item => `<li>${item}</li>`).join('')}
    </ul>
    <button id="append">추가</button>
  `;
  /* 클릭 이벤트가 발생하면 setState( ) 실행 */
  document.querySelector('#append').addEventListener('click', () => {
    setState({ items: [ ...items, `item${items.length + 1}` ] })
  })
}

/* setState ( ) 함수가 실행되면 자동으로 render( ) 함수 호출 */
const setState = (newState) => {
  state = { ...state, ...newState };
  render();
}

/* 초기값 렌더링 */
render();
</script>

✔️ state 값을 직접 변경해도 render( ) 함수는 새로 호출되지 않는다. setState( ) 함수를 호출하여 state 값을 변경하면 자동으로 render( ) 함수를 호출하므로 화면에 변경된 state 값을 새롭게 출력할 수 있다.

✔️ setState( ) 함수의 인자로 함수를 전달하면 이전 state 값을 읽는 과정을 생략할 수 있다.


앞서 작성한 코드를 class 문법으로 추상화시켜보자.

<div id="app"></div>
<script>
class Component {
  $target;
  $state;
  constructor ($target) { 
    this.$target = $target;
    this.setup();
    this.render();
  }
  
  setup () {};
  template () { return ''; }
  
  render () {
    this.$target.innerHTML = this.template();
    this.setEvent();
  }
  setEvent () {}
  setState (newState) {
    this.$state = { ...this.$state, ...newState };
    this.render();
  }
}

class App extends Component {
  setup () {
    this.$state = { items: ['item1', 'item2'] };
  }
  template () {
    const { items } = this.$state;
    return `
        <ul>
          ${items.map(item => `<li>${item}</li>`).join('')}
        </ul>
        <button>추가</button>
    `
  }
  
  setEvent () {
    this.$target.querySelector('button').addEventListener('click', () => {
      const { items } = this.$state;
      this.setState({ items: [ ...items, `item${items.length + 1}` ] });
    }); 
  }
}

new App(document.querySelector('#app'));
</script>
profile
오늘도 신나개 🐶

0개의 댓글