티스토리 뷰

learning

[WAVE] 'React' 와 그 무리들

눈침침 2021. 1. 30. 01:26

(우선 '[WAVE]' 란 나를 퇴출로 밀어내려는 공격을 의미합니다.)

 

 어리바리 코드를 보기 시작했는데, 'React'와 그 무리들덕분에 멘붕이 찾아왔다.(React 이 녀석은 때로 몰려다니는 녀석인가보다.., 그리고 사실 매일매일 수차례 멘붕을 겪고 있다.) 지금 이 모든 걸 이해하는 건 쉽지 않으니 어디에 쓰는 녀석인지만 알아보자.

귀가 닳도록 들어본 'React'

ko.reactjs.org/

React – 사용자 인터페이스를 만들기 위한 JavaScript 라이브러리

A JavaScript library for building user interfaces

ko.reactjs.org

사용자 인터페이스를 만들기 위한 JavaScript 라이브러리

선언형

  • 애플리케이션의 각 상태에 대한 간단한 뷰만 설계하세요. 그럼 React는 데이터가 변경됨에 따라 적절한 컴포넌트만 효율적으로 갱신하고 렌더링 합니다.

컴포넌트 기반

  • 스스로 상태를 관리하는 캡슐화된 컴포넌트
  • 컴포넌트 로직은 템플릿이 아닌 JavaScript로 작성
  • DOM과는 별개로 상태를 관리 (무슨 뜻일까?)

한 번 배워서 어디서나 사용하기

  • 기술 스택의 나머지 부분에는 관여하지 않기 때문에, 기존 코드를 다시 작성하지 않고도 React의 새로운 기능을 이용해 개발할 수 있습니다. ( 과연.. )

간단한 컴포넌트

  • React 컴포넌트는 render()라는 메서드를 통해 화면에 표시할 내용을 반환
  • 컴포넌트로 전달된 데이터는 render() 안에서 this.props를 통해 접근

상태를 가지는 컴포넌트

  • 컴포넌트는 this.props를 이용해 입력 데이터를 다룸
  • 내부적인 상태 데이터는 this.state로 접근
  • 컴포넌트의 상태 데이터가 바뀌면 render()가 다시 호출되어 마크업이 갱신

샘플 코드

class TodoApp extends React.Component {
  constructor(props) {
    super(props);
    this.state = { items: [], text: '' };
    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  render() {
    return (
      <div>
        <h3>TODO</h3>
        <TodoList items={this.state.items} />
        <form onSubmit={this.handleSubmit}>
          <label htmlFor="new-todo">
            What needs to be done?
          </label>
          <input
            id="new-todo"
            onChange={this.handleChange}
            value={this.state.text}
          />
          <button>
            Add #{this.state.items.length + 1}
          </button>
        </form>
      </div>
    );
  }

  handleChange(e) {
    this.setState({ text: e.target.value });
  }

  // 'form' 안의 'button' 의 기본 type 인 'submit' 으로 인해 'button' 클릭시 자동 호출.
  handleSubmit(e) {
    e.preventDefault();
    if (this.state.text.length === 0) {
      return;
    }
    const newItem = {
      text: this.state.text,
      id: Date.now()
    };
    this.setState(state => ({
      items: state.items.concat(newItem),
      text: ''
    }));
  }
}

class TodoList extends React.Component {
  render() {
    return (
      <ul>
        {this.props.items.map(item => (
          <li key={item.id}>{item.text}</li>
        ))}
      </ul>
    );
  }
}

ReactDOM.render(
  <TodoApp />,
  document.getElementById('todos-example')
);

ReactDOM

ko.reactjs.org/docs/react-dom.html

ReactDOM – React

A JavaScript library for building user interfaces

ko.reactjs.org

React를 <script> 태그로 불러온다면, ReactDOM 글로벌 영역에서 상위 레벨 API를 이용할 수 있습니다. (무슨 말인지 모르겠다)

홈페이지에 개요에 나오는 함수들을 읽어보니 대략 역할이 보인다. React 컴포넌트를 포함하여 React로 렌더링 된 결과를 render() 함수 등을 이용하여 DOM 요소 안에 그리는 역할을 하나 봄.

(샘플 코드는 아래 React Redux를 살펴보자)

 


React Redux

react-redux.js.org/introduction/quick-start

Quick Start | React Redux

Quick Start

react-redux.js.org

React Redux는 Redux의 공식 React 바인딩

Provider

Provider로 가져와서 React 컴포넌트를 감싸면 컴포넌트에서 다 함께 저 store라는 녀석을 바라볼 수 있는 건가 보다.

import React from 'react'
import ReactDOM from 'react-dom'

import { Provider } from 'react-redux'
import store from './store'

import App from './App'

const rootElement = document.getElementById('root')
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
)

connect()

컴포넌트에서 Store 값을 이용하는 데 사용하는 듯.

mapStateToProps와 mapDispatchToProps 두 개를 인자로 받고,

mapStateToProps는 store에서 값을 가져와 처리하는 부분(store 가 변경되면 다시 호출됨)

mapDispatchToProps는 store로 값을 반영시키는(Dispatch) 역할을 함

.. 잘 모르겠다 나중에 더 자세히 봐야 할 듯..

 


뭔가 쉽지 않은 녀석이라 들었던, Redux

redux.js.org/

Redux - A predictable state container for JavaScript apps. | Redux

A predictable state container for JavaScript apps.

redux.js.org

'예측 가능한 상태 저장소' 라..

사용법은 간단해 보인다.

import { createStore } from 'redux'

// 'createStore' 의 인자.
function counterReducer(state = { value: 0 }, action) {
  
  // 'state' 는 현재 상태 객체이고, 없다면 { value: 0 } (요런것도 가능하군..)
  // 'dispatch' 의 결과가 action 으로 전달되는 듯.
  switch (action.type) {
    case 'counter/incremented':
      return { value: state.value + 1 }
    case 'counter/decremented':
      return { value: state.value - 1 }
    default:
      return state
  }
}

// 저장소를 만들고.
let store = createStore(counterReducer)

// 값의 변경을 구독하고.
store.subscribe(() => console.log(store.getState()))

// 변경을 전파 함
store.dispatch({ type: 'counter/incremented' })

redux 뭔지 감이오니 이제 그만.


redux-thunk

github.com/reduxjs/redux-thunk

reduxjs/redux-thunk

Thunk middleware for Redux. Contribute to reduxjs/redux-thunk development by creating an account on GitHub.

github.com

'redux' 미들웨어라..

'redux'의 'store'에 값을 dispatch로 업데이트하는데 요 녀석을 쓰면 더 다양하게(ex, 비동기) 업데이트할 수 있다고 하는 듯.

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';

// Note: this API requires redux@>=3.1.0
const store = createStore(rootReducer, applyMiddleware(thunk));

redux 가 applyMiddleware로 미들웨어 확장 기능을 제공하는 듯.

function makeASandwichWithSecretSauce(forPerson) {
  return function(dispatch) {
    return fetchSecretSauce().then(
      (sauce) => dispatch(makeASandwich(forPerson, sauce)),
      (error) => dispatch(apologize('The Sandwich Shop', forPerson, error)),
    );
  };
}

// dispatch 의 인자로 함수를 넘기면, trunk 가 받아서,
// 해당 함수를 (dispatch, getSource)를 인자로 전달하여 호출해줌.
store.dispatch(makeASandwichWithSecretSauce('Me'));

// Promise 로 연결해서 처리도 가능.
store.dispatch(makeASandwichWithSecretSauce('My partner')).then(() => {
  console.log('Done!');
});

'withExtraArgument'로 thunk 가 호출할 때 세 번째 인자를 넘길 수도 있다.

const api = "http://www.example.com/sandwiches/";
const whatever = 42;

const store = createStore(
  reducer,
  applyMiddleware(thunk.withExtraArgument({ api, whatever })),
);

// later
function fetchUser(id) {
  return (dispatch, getState, { api, whatever }) => {
    // you can use api and something else here
  };
}

음.. 'redux-thunk'는 완전히 이해한 것 같다;;


redux-logger

github.com/LogRocket/redux-logger

LogRocket/redux-logger

Logger for Redux. Contribute to LogRocket/redux-logger development by creating an account on GitHub.

github.com

요 녀석도 'redux' 미들웨어이고, 'store'의 변경정보를 콘솔에 보기 좋게 남기는 용도인 듯

샘플 코드

import { applyMiddleware, createStore } from 'redux';

// Logger with default options
import logger from 'redux-logger'
const store = createStore(
  reducer,
  applyMiddleware(logger)
)

react-modal

github.com/reactjs/react-modal

reactjs/react-modal

Accessible modal dialog component for React. Contribute to reactjs/react-modal development by creating an account on GitHub.

github.com

React로 만들어진 모달 창 컴포넌트

import React from 'react';
import ReactDOM from 'react-dom';
import Modal from 'react-modal';


// 모달을 표시할 DOM 요소를 지정.
Modal.setAppElement('#yourAppElement')

function App(){

    // ... 생략 (전체 코드는 홈페이지에서 보자!!) .. 
    
    // 아래 <Modal> 과 같이 사용.
    // 표시 여부는 isOpen 속성을 이용.
    return (
      <div>
        <button onClick={openModal}>Open Modal</button>
        <Modal
          isOpen={modalIsOpen}
          onAfterOpen={afterOpenModal}
          onRequestClose={closeModal}
          style={customStyles}
          contentLabel="Example Modal"
        >

          <h2 ref={_subtitle => (subtitle = _subtitle)}>Hello</h2>
          <button onClick={closeModal}>close</button>
          <div>I am a modal</div>
          <form>
            <input />
            <button>tab navigation</button>
            <button>stays</button>
            <button>inside</button>
            <button>the modal</button>
          </form>
        </Modal>
      </div>
    );
}

ReactDOM.render(<App />, appElement);

redux-devtools-extension

github.com/zalmoxisus/redux-devtools-extension

zalmoxisus/redux-devtools-extension

Redux DevTools extension. Contribute to zalmoxisus/redux-devtools-extension development by creating an account on GitHub.

github.com

브라우저 확장 툴과 함께 'Redux' 'Store'를 보고 특정 순간으로 되돌리거나 발생한 이벤트(=Dispatchers)를 재현하는 기능 등이 있는 듯.

 


글 쓰기 시작할 때의 막막함은 어느 정도 사라진 듯 하니, 목표 달성!! 야호!!

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함