5. 리덕스 중급과정 : 미들웨어

hhkim·2021년 7월 17일
0
post-thumbnail

모던 리액트(React)와 리덕스(Redux)

강사 Github


컴포넌트와 컨텍스트 바인딩

참고

  • 아래 코드에서 input에 변화가 있으면 onInputChange가 호출되는데 이때 onInputChange 내부의 this.setState()undefined이다.
    • onChange의 이벤트리스너로 onInputChange를 할당함으로써 새로운 함수가 생겨났고, 그 함수가 호출되는 것이기 때문
  • 이전에는 화살표 함수를 사용해서 가능 (화살표 함수는 this를 자동으로 바인딩해준다.)
    onChange={(event) => onInputChange(event)}
    • 그런데 이렇게 render() 내부에서 바인딩을 하게 되면 렌더링마다 새로운 함수가 생겨나서 성능을 떨어뜨릴 수 있다.
// components/search_bar.js
export default class SearchBar extends Component {
  constructor(props) {
    ...
  }

  onInputChange(event) {
    this.setState({ term: event.target.value });
  }

  render() {
    return (
      <form className="input-group">
        <input
          ...
          value={this.state.term}
          onChange={this.onInputChange}
        />
        ...
      </form>
    );
  }
}
  • 이를 해결하기 위해 아래와 같이 constructor에서 컴포넌트와 컨텍스트 바인딩을 해준다.
constructor(props) {
    super(props);

    this.state = { term: '' };
	
    // onInputChange함수에 SearchBar 컴포넌트를 바인딩하여 덮어씌운다.
    this.onInputChange = this.onInputChange.bind(this);
  }

👉 이벤트 핸들러를 레퍼런스로 전달하고, 컴포넌트와 생성자에서 바인딩함으로써 최적화한 코드 완성!


미들웨어

액션 생성자에서 리듀서 사이에서 액션을 가로채어 액션을 막거나 수정하는 등 일종의 문지기 역할을 한다.

  • npm install --save redux-promise: redux-promise 설치 (Ajax 요청 처리를 위해서)
  • 리덕스 프로젝트에 미들웨어 연결
...
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
// redux-promise 가져오기
import ReduxPromise from 'redux-promise';

import App from './components/app';
import reducers from './reducers';

// applyMiddleware의 첫 번째 인자로 ReduxPromise 보내기
const createStoreWithMiddleware = applyMiddleware(ReduxPromise)(createStore);

ReactDOM.render(
  ...
);

Ajax 리퀘스트

  • npm install --save axios: axios 설치
  • axios.get(url): url에 대한 ajax 리퀘스트
    • promise를 리턴
// actions/index.js
import axios from 'axios';
...
// 리듀서에서 오타로 인한 문제를 막기 위해 변수를 선언
export const FETCH_WEATHER = 'FETCH_WEATHER';

export function fetchWeather(city) {
  const url = `${ROOT_URL}&q=${city},us`;
  const request = axios.get(url);

  return {
    type: FETCH_WEATHER,
    payload: request,
  };
}

redux-promise 활용

미들웨어와 액션 흐름
1. 액션 생성자가 액션 리턴
2. 미들웨어로 들어감
3. 액션이 payload 값으로 promise를 가지고 있는지 판단

  • 그렇다
    1. 액션 멈춤
    2. promise를 풀어서 새로운 액션을 생성한 다음 리듀서로 보냄
    3. 리듀서 실행
  • 아니다
    1. 그냥 놔둠
    2. 리듀서 실행

👉 굳이 비동기 데이터를 다루는 코드를 작성하지 않았지만 미들웨어를 통해 비동기 요청과 promise를 관리하여 깔끔한 코드 유지


스테이트 변조 피하기

  • state를 직접 변경하면 안 되기 때문에 push() 대신 concat()을 호출하여 새로운 배열을 만든다.
// reducers/reducer_weather.js
import { FETCH_WEATHER } from '../actions/index';

export default function (state = [], action) {
  switch (action.type) {
    case FETCH_WEATHER:
      return [action.payload.data, ...state];
  }
  return state;
}
return state.concat([action.payload.data]);

ES6 문법을 사용하여 아래와 같이 작성할 수 있다.

return [action.payload.data, ...state];

새로운 배열을 만드는데, 첫 번째 요소는 action.payload.data이고 다음 요소는 state의 모든 요소를 가져와서 넣어준다.


스파크라인 차트 추가

  • npm install --save react-sparklines: react-sparklines 설치
  • import하고 문서 참고해서 차트 작성 가능
// components/chart.js
import React from 'react';
import { Sparklines, SparklinesLine } from 'react-sparklines';

export default (props) => {
  return (
    <div>
      <Sparklines height={120} width={180} data={props.data}>
        <SparklinesLine color={props.color} />
      </Sparklines>
    </div>
  );
};
// containers/weather_list.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Chart from '../components/chart';

class WeatherList extends Component {
  renderWeather(cityData) {
    const name = cityData.city.name;
    const temps = cityData.list.map((weather) => weather.main.temp);

    return (
      <tr key={name}>
        <td>{name}</td>
        <td>
          <Chart data={temps} color="orange" />
        </td>
      </tr>
    );
  }
  render() {
    ...
  }
}
...

구글맵 추가

const lon = cityData.city.coord.lon;
const lat = cityData.city.coord.lat;

위의 코드와 아래 코드는 동일하다.

const { lon, lat } = cityData.city.coord;

JSX DOM에 스타일 지정

<div style={{ height: '100%' }} />
  • 바깥 괄호({})는 자바스크립트 문법
  • 안쪽 괄호({})는 자바스크립트 오브젝트

여긴 어디... 나는 누구...

0개의 댓글