Redux 감속기 작동 방식

게시 됨: 2022-03-10
빠른 요약 ↬ state 를 관리하기 위한 애플리케이션을 개발하는 동안 Redux를 사용한 적이 있다면 가장 확실히 리듀서를 접했을 것입니다. 이 튜토리얼에서는 감속기의 개념과 Redux에서 구체적으로 어떻게 작동하는지 설명합니다.

이 튜토리얼에서는 감속기의 개념과 특히 React 애플리케이션에서 어떻게 작동하는지 배울 것입니다. Redux를 이해하고 더 잘 사용하려면 리듀서에 대한 확실한 이해가 필수적입니다. 리듀서는 작업을 사용하여 애플리케이션의 상태를 업데이트하는 방법을 제공합니다. Redux 라이브러리의 필수적인 부분입니다.

이 튜토리얼은 Redux Reducers에 대해 더 배우고자 하는 개발자를 위한 것입니다. React와 Redux에 대한 이해가 도움이 될 것입니다. 튜토리얼이 끝나면 Redux에서 Reducers의 역할을 더 잘 이해하게 될 것입니다. Reducer와 이것이 애플리케이션의 상태에 미치는 영향을 더 잘 이해하기 위해 코드 데모와 애플리케이션을 작성할 것입니다.

감속기 란 무엇입니까

Reducer는 애플리케이션과 액션의 상태를 인수로 받아 새 상태를 반환하는 순수 함수입니다. 예를 들어, 인증 감소기는 빈 객체의 형태로 애플리케이션의 초기 상태와 사용자가 로그인하고 로그인한 사용자와 함께 새 애플리케이션 상태를 반환했음을 알려주는 작업을 취할 수 있습니다.

순수 함수는 부작용이 없는 함수이며 동일한 인수가 전달되면 동일한 결과를 반환합니다.

다음은 순수 함수의 예입니다.

 const add = (x, y) => x + y; add(2, 5);

위의 예는 입력을 기반으로 한 값을 반환합니다. 25 를 전달하면 항상 7 을 얻습니다. 동일한 입력이면 얻는 출력에 영향을 주지 않는 한 순수 함수의 예입니다.

다음은 상태와 동작을 취하는 리듀서 함수의 예입니다.

 const initialState = {}; const cartReducer = (state = initialState, action) => { // Do something here }

리듀서가 받는 두 개의 매개변수 stateaction 을 정의해 보겠습니다.

점프 후 더! 아래에서 계속 읽기 ↓

상태

상태 는 구성 요소가 작업하는 데이터입니다. 구성 요소에 필요한 데이터를 보유하고 구성 요소가 렌더링하는 내용을 지정합니다. state 개체가 변경되면 구성 요소가 다시 렌더링됩니다. 애플리케이션 상태가 Redux에 의해 관리된다면 리듀서는 상태 변경이 일어나는 곳입니다.

동작

작업 은 정보의 페이로드를 포함하는 개체입니다. 업데이트할 Redux 저장소에 대한 유일한 정보 소스입니다. 리듀서는 action.type 값을 기반으로 저장소를 업데이트합니다. 여기에서 action.typeADD_TO_CART 로 정의합니다.

공식 Redux 문서에 따르면 작업은 Redux 응용 프로그램에서 변경을 트리거하는 유일한 항목이며 응용 프로그램 저장소 변경에 대한 페이로드를 포함합니다. 액션은 Redux에 수행할 액션 유형을 알려주는 JavaScript 객체이며 일반적으로 아래와 같은 함수로 정의됩니다.

 const action = { type: 'ADD_TO_CART', payload: { product: 'margarine', quantity: 4 } }

위의 코드는 사용자가 보내는 내용을 포함하는 일반적인 payload 값이며 애플리케이션의 상태를 업데이트하는 데 사용됩니다. 위에서 볼 수 있듯이 action 객체에는 action의 유형과 이 특정 작업을 수행하는 데 필요한 페이로드 객체가 포함되어 있습니다.

리듀서를 사용하여 상태 업데이트

감속기가 어떻게 작동하는지 보여주기 위해 아래 숫자 카운터를 살펴보겠습니다.

 const increaseAction = { type: 'INCREASE', }; const decreaseAction = { type: 'DECREASE' }; const countReducer = (state = 0, action) => { switch(action.type){ case INCREASE: return state + 1; case DECREASE : return state -1; default: return state; } };

위의 코드에서 increaseAction 액션 및 decreaseAction 액션은 state 가 업데이트될 대상을 결정하기 위해 리듀서에서 사용되는 작업입니다. 다음으로 countReducer 라는 리듀서 함수가 있습니다. 이 함수는 값이 0 인 초기 stateaction 을 취합니다. action.type 의 값이 INCREASE 이면 1만큼 증가된 새 상태를 반환하고, 그렇지 않으면 DECREASE 이면 1만큼 감소한 새 상태를 반환합니다. 이러한 조건 중 어느 것도 의미하지 않는 경우 state 를 반환합니다.

리듀서를 사용한 상태 업데이트: 스프레드 연산자

상태는 직접 변경할 수 없습니다. 상태를 생성하거나 업데이트하기 위해 JavaScript 확산 연산자를 사용하여 상태 값을 직접 변경하지 않고 대신 전달된 상태를 포함하는 새 객체를 반환하도록 할 수 있습니다. 사용자의 페이로드.

 const contactAction = { type: 'GET_CONTACT', payload: ['0801234567', '0901234567'] }; const initialState = { contacts: [], contact: {}, }; export default function (state = initialState, action) { switch (action.type) { case GET_CONTACTS: return { ...state, contacts: action.payload, }; default: return state; }

위의 코드에서 우리는 상태 값을 직접 변경하지 않기 위해 스프레드 연산자를 사용하고 있습니다. 이렇게 하면 전달된 상태와 페이로드로 채워진 새 개체를 반환할 수 있습니다. 사용자. 스프레드 연산자를 사용하여 모든 새 항목을 추가할 때 상태가 동일하게 유지되도록 할 수 있으며 이전에 존재했던 경우 해당 상태의 연락처 필드도 교체할 수 있습니다.

작동 중인 Redux 감속기 — 데모

Redux Reducers와 작동 방식을 더 잘 이해하기 위해 간단한 영화 세부 정보 찾기 앱을 구현할 것입니다. 코드 및 작업 버전은 여기 Codesandbox에서 찾을 수 있습니다. 시작하려면 터미널로 이동하여 아래 명령을 사용하여 반응 앱을 초기화하십시오.

 create-react-app movie-detail-finder

프로젝트가 초기화되면 다음으로 애플리케이션에 필요한 패키지를 설치하겠습니다.

 npm i axios reactstrap react-redux redux redux-thunk

패키지가 설치되면 다음 명령을 사용하여 개발 서버를 시작하겠습니다.

 npm start

위의 명령은 브라우저에서 프로젝트 개발 서버를 시작해야 합니다. 다음으로 선택한 텍스트 편집기에서 프로젝트를 열고 프로젝트 src 폴더 내에서 App.css , App.test.js , serviceWorker.jssetupTests.js 파일을 삭제합니다. 다음으로 App.js 에서 삭제된 파일을 참조하는 모든 코드를 삭제하겠습니다.

이 프로젝트의 경우 Open Movie Database API를 사용하여 애플리케이션에 대한 영화 정보, 콘텐츠 및 이미지를 가져올 것입니다. 여기에 API에 대한 링크가 있습니다. 이를 사용하려면 등록하고 액세스 키를 가져와야 합니다. 응용 프로그램이 완료되면 구성 요소를 빌드하여 응용 프로그램을 계속 진행해 보겠습니다.

앱 구성 요소 빌드

먼저 프로젝트 디렉토리의 src 폴더 안에 components라는 폴더를 만들고 폴더 안에 MovieSearchbar 라는 두 개의 폴더를 만들어 보겠습니다. 구성 요소는 아래 이미지와 같아야 합니다.

구성 요소 폴더
구성 요소 폴더. (큰 미리보기)

영화 구성 요소 구축

API에서 가져올 영화 세부 정보의 구조를 간략하게 설명하는 Movies 구성 요소를 빌드해 보겠습니다. 이렇게 하려면 구성 요소의 Movies 폴더 내에서 새 파일 Movie.js 를 만들고 다음으로 API 결과에 대한 클래스 기반 구성 요소를 만듭니다. 아래에서 수행하겠습니다.

 import React, { Component } from 'react'; import { Card, CardImg, CardText, CardBody, ListGroup, ListGroupItem, Badge } from 'reactstrap'; import styles from './Movie.module.css'; class Movie extends Component{ render(){ if(this.props.movie){ return ( <div className={styles.Movie}> <h3 className="text-center my-4"> Movie Name: {this.props.movie.Title} </h3> <Card className="text-primary bg-dark"> <CardImg className={styles.Img} top src={this.props.movie.Poster} alt={this.props.movie.Title}/> <CardBody> <ListGroup className="bg-dark"> <ListGroupItem> <Badge color="primary">Actors:</Badge> {this.props.movie.Actors} </ListGroupItem> <ListGroupItem> <Badge color="primary">Genre:</Badge> {this.props.movie.Genre} </ListGroupItem> <ListGroupItem> <Badge color="primary">Year:</Badge> {this.props.movie.Year} </ListGroupItem> <ListGroupItem> <Badge color="primary">Writer(s):</Badge> {this.props.movie.Writer} </ListGroupItem> <ListGroupItem> <Badge color="primary">IMDB Rating:</Badge> {this.props.movie.imdbRating}/10 </ListGroupItem> </ListGroup> <CardText className="mt-3 text-white"> <Badge color="secondary">Plot:</Badge> {this.props.movie.Plot} </CardText> </CardBody> </Card> </div> ) } return null } } export default Movie;

위의 코드에서 패키지 reactstrap 의 구성 요소 사용 에서 문서를 여기에서 확인할 수 있습니다. 우리는 영화 이름, 이미지, 장르, 배우, 연도, 영화 작가, 등급 및 줄거리를 포함하는 카드 구성 요소를 만들었습니다. 이 구성 요소에서 데이터를 쉽게 전달할 수 있도록 데이터를 다른 구성 요소에 대한 소품으로 만들었습니다. 다음으로 Searchbar 구성 요소를 빌드해 보겠습니다.

검색창 구성요소 만들기

Searchbar 표시줄 구성 요소에는 영화 구성 요소를 검색하기 위한 검색 표시줄과 버튼 구성 요소가 있습니다. 아래에서 수행하겠습니다.

 import React from 'react'; import styles from './Searchbar.module.css'; import { connect } from 'react-redux'; import { fetchMovie } from '../../actions'; import Movie from '../Movie/Movie'; class Searchbar extends React.Component{ render(){ return( <div className={styles.Form}> <div> <form onSubmit={this.formHandler}> <input type="text" placeholder="Movie Title" onChange={e => this.setState({title: e.target.value})} value={this.state.title}/> <button type="submit">Search</button> </form> </div> <Movie movie={this.props.movie}/> </div> ) } }

위의 코드에서는 React 구성 요소를 Redux 저장소에 연결하는 데 사용되는 react-redux 에서 connect 을 가져오고 구성 요소에 저장소의 정보를 제공하며 저장소에 작업을 전달하는 데 사용되는 기능도 제공합니다. 다음으로 액션에서 Movie 구성 요소와 fetchMovie 함수를 가져왔습니다.

다음으로, 영화 제목을 입력하기 위한 입력 상자가 있는 양식 태그가 있습니다. React의 setState 후크를 사용하여 onChange 이벤트와 title 상태를 입력 상자에 입력된 값으로 설정하는 값을 추가했습니다. 영화 제목을 검색하기 위한 button 태그가 있고 가져온 Movie 컴포넌트를 사용하여 컴포넌트의 속성을 검색 결과에 props 로 전달했습니다.

다음은 우리에게 결과를 보내기 위해 API에 영화 제목을 제출하는 함수를 작성하는 것입니다. 또한 애플리케이션의 초기 상태를 설정해야 합니다. 아래에서 해보자.

 class Searchbar extends React.Component{ state = { title: '' } formHandler = (event) => { event.preventDefault(); this.props.fetchMovie(this.state.title); this.setState({title: ''}); }

여기에서 애플리케이션의 초기 상태를 빈 문자열로 설정하고 이벤트 매개변수를 받아 action에서 fetchMovie 함수를 전달하고 제목을 애플리케이션의 새 상태로 설정하는 함수 formHandler 를 생성했습니다. 애플리케이션을 완성하기 위해 react-redux 의 연결 속성을 사용하여 이 구성 요소를 내보내겠습니다. 이를 위해 react redux mapToStateProps 속성을 사용하여 구성 요소에 필요한 데이터 부분을 선택합니다. 여기에서 mapToStateProps 에 대해 자세히 알아볼 수 있습니다.

 const mapStateToProps = (state) => { return { movie: state.movie } } export default connect(mapStateToProps, { fetchMovie })(Searchbar)

Searchbar.module.css 파일을 만들고 아래 스타일을 추가하여 양식에 스타일을 추가해 보겠습니다.

 .Form{ margin: 3rem auto; width: 80%; height: 100%; } input{ display: block; height: 45px; border: none; width: 100%; border-radius: 0.5rem; outline: none; padding: 0 1rem; } input:focus, select:focus{ border: 2px rgb(16, 204, 179) solid; } .Form button{ display: block; background: rgb(16, 204, 179); padding: 0.7rem; border-radius: 0.5rem; width: 20%; margin-top: 0.7rem; color: #FFF; border: none; text-decoration: none; transition: all 0.5s; } button:hover{ opacity: 0.6; } @media(max-width: 700px){ input{ height: 40px; padding: 0 1rem; } .Form button{ width: 40%; padding: 0.6rem; } }

위의 작업을 완료하면 검색 표시줄 구성 요소가 아래 이미지와 유사하게 보일 것입니다.

검색창 구성요소
검색창 구성요소. (큰 미리보기)

응용 프로그램에 대한 작업 생성

이 구성 요소에서 애플리케이션에 대한 Redux 작업을 설정할 것입니다. 먼저 src 디렉토리 안에 actions 라는 폴더를 만들고 폴더 안에 index.js 파일을 만듭니다. 여기에서 title 매개변수를 받고 Axios를 사용하여 API에서 영화를 가져오는 fetchMovie 함수를 만듭니다. 아래와 같이 해보자.

 import axios from 'axios'; export const fetchMovie = (title) => async (dispatch) => { const response = await axios.get( `https://cors-anywhere.herokuapp.com/https://www.omdbapi.com/?t=${title}&apikey=APIKEY`); dispatch({ type: 'FETCH_MOVIE', payload: response.data }) }

위의 코드에서 우리는 axios 를 가져오고 API 서버에 요청할 수 있도록 async/await를 사용하여 title 매개변수를 fetchMovie 라는 함수를 만들었습니다. Redux에 전달되는 액션 객체에 디스패치하는 dispatch 함수가 있습니다. 위의 내용에서 FETCH_MOVIE 유형의 작업과 API에서 얻은 응답이 포함된 페이로드를 전달합니다.

참고: 요청의 apikey 는 OmdbAPI에 등록한 후 자신의 apikey 로 대체됩니다 .

앱 리듀서 만들기

이 섹션에서는 애플리케이션에 대한 감속기를 만들 것입니다.

 const fetchMovieReducer = (state = null, action) => { switch(action.type){ case 'FETCH_MOVIE': return action.payload; default: return state; } } const rootReducer = (state, action) => { return { movie: fetchMovieReducer(state, action) } } export default rootReducer;

위의 코드에서 우리는 fetchMovieReducernull FETCH_MOVIE 에서 가져온 영화인 action.payload 의 값을 반환 action 것입니다. 수행하려고 시도한 작업이 감속기에 없으면 기본 상태를 반환합니다.

다음으로 현재 상태와 작업을 입력으로 fetchMovieReducer 를 반환하는 rootReducer 함수를 만들었습니다.

함께 넣어

이 섹션에서는 index.js 에 redux 저장소를 만들어 앱을 완성합니다. 아래에서 수행하겠습니다.

 import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; import { createStore, applyMiddleware } from 'redux'; import thunk from 'redux-thunk'; import App from './App'; import 'bootstrap/dist/css/bootstrap.min.css'; import './index.css'; import reducers from './reducers'; const store = createStore(reducers, applyMiddleware(thunk)) ReactDOM.render( <Provider store={store}> <> <App/> </> </Provider>, document.getElementById('root') )

위의 코드에서 생성한 리듀서와 미들웨어를 전달하여 createStore 메소드를 사용하여 애플리케이션 store 를 생성했습니다. 미들웨어는 Redux의 기능을 향상시킬 수 있는 애드온입니다. 여기에서는 applyMiddleware를 사용하여 Redux applyMiddleware 미들웨어를 사용하고 있습니다. Redux Thunk 미들웨어는 스토어가 비동기식 업데이트를 수행하는 데 필요합니다. 이것은 기본적으로 Redux가 저장소를 동기식으로 업데이트하기 때문에 필요합니다.

애플리케이션이 사용할 정확한 저장소를 알고 있는지 확인하기 위해 애플리케이션을 Provider 구성 요소에 래핑하고 저장소를 소품으로 전달했습니다. 이렇게 하면 애플리케이션의 다른 구성 요소가 연결하고 저장소와 정보를 공유할 수 있습니다.

index.css 파일에 약간의 스타일을 추가해 보겠습니다.

 *{ margin: 0; padding: 0; box-sizing: border-box; } body{ background: rgb(15, 10, 34); color: #FFF; height: 100vh; max-width: 100%; }

Movie Detail Finder 렌더링 및 테스트

이 섹션에서는 App.js 에서 응용 프로그램을 렌더링하여 응용 프로그램을 마무리할 것입니다. 이를 위해 App 이라는 클래스 기반 구성 요소를 만들고 검색 표시줄 및 입력 필드를 초기화하겠습니다.

 import React from 'react'; import Searchbar from './components/Searchbar/Searchbar'; import styles from './App.module.css'; class App extends React.Component{ render(){ return( <div className={styles.App}> <h1 className={styles.Title}>Movies Search App</h1> <Searchbar/> </div> ) } } export default App;

여기에서 Movie Search App이라는 h1 을 사용하여 App 클래스 기반 구성 요소를 만들고 Searchbar 구성 요소를 추가했습니다. 애플리케이션은 아래 이미지와 같아야 합니다.

감속기가 있는 영화 세부 정보 응용 프로그램
감속기를 사용한 최종 영화 세부 정보 응용 프로그램. (큰 미리보기)

Codesandbox에서 작동하는 데모를 사용할 수 있습니다.

결론

리듀서는 Redux 상태 관리의 중요한 부분입니다. 리듀서를 사용하면 부작용 없이 Redux 애플리케이션의 특정 영역을 업데이트하는 순수한 기능을 작성할 수 있습니다. Redux 리듀서의 기본, 사용법, 리듀서, 상태 및 인수의 핵심 개념을 배웠습니다.

여기에서 Redux 리듀서에 대한 문서를 보면 더 자세히 알 수 있습니다. 이것을 더 발전시켜 Redux 리듀서에 더 많은 것을 구축할 수 있습니다. 무엇을 구축했는지 알려주십시오.

자원

  • React-Redux 문서
  • 리덕스 문서
  • connect() 함수
  • applyMiddleware 기능