(우선 '[WAVE]' 란 나를 퇴출로 밀어내려는 공격을 의미합니다.)
어리바리 코드를 보기 시작했는데, 'React'와 그 무리들덕분에 멘붕이 찾아왔다.(React 이 녀석은 때로 몰려다니는 녀석인가보다.., 그리고 사실 매일매일 수차례 멘붕을 겪고 있다.) 지금 이 모든 걸 이해하는 건 쉽지 않으니 어디에 쓰는 녀석인지만 알아보자.
귀가 닳도록 들어본 'React'
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 - 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)를 재현하는 기능 등이 있는 듯.
글 쓰기 시작할 때의 막막함은 어느 정도 사라진 듯 하니, 목표 달성!! 야호!!