Redux-Thunk 학습 곡선 등반

31466 단어 reactreduxjavascript

선언:
나는 전문가가 아니다.저는 React를 배우고 있습니다. Thunk과 Redux를 배우고 싶습니다.이것은 내가 나의 학습 과정을 기록하고 고개를 돌려 다른 사람들이 똑같은 일을 하는 것을 돕는 것과 관련된 것을 시도하는 것이다.
나는 내가 마지막으로 찾은 가장 유용한 자원과 글을 연결하고 있다.그들은 전문가다.내가 가장 도움이 되는 공헌은 아마도 아까처럼 익숙하지 않은 학습 곡선을 기어오르는 사람들을 돕는 것일 것이다.일단 네가 거기에 도착하면 그 사람들은 너를 데리고 집에 갈 것이다.
본고는 독자들도 자바스크립트를 배우고 Redux에 익숙하다고 가정한다.Redux에 대해 간략하게 설명하겠습니다.그러나 본고는 Thunk를 Redux로 해석하는 확장과 관련된다.나는 또한 Thunk 용례를 토론하고 예시를 제공할 것이다.

Redux는 무엇입니까? Redux는 우리를 위해 무엇을 했습니까?

“Redux was created by Dan Abramov for a . It is a “state container” inspired by the unidirectional Flux data flow and functional Elm architecture. It provides a predictable approach to managing state that benefits from immutability, keeps business logic contained, acts as the single source of truth, and has a very small API.” --Gabriel Lebec


웹 사이트를 불러오고 계정에 로그인하면 응용 프로그램은 데이터베이스와 다른 곳에서 우리의 개성화된 사용자 체험을 위해 데이터를 추출하여 '수합' 이나 응용 프로그램을 시작합니다.생각해봐...내 모든 사용자가 선호하는 데이터, 게시물, 취향, 내 위치의 날씨 데이터 등. 이 데이터를 얻으면 우리 프로그램의 '상태', 그리고 우리가 응용 프로그램에서 체험하는 환경이 된다.이 모든 것은 기본적으로 로컬에 저장된다.우리가 브라우저와 상호작용을 할 때...좋아, 필터 전환, 삭제 등등...응용 프로그램의 상태는 우리가 경험한 환경(즉 우리가 있는 페이지)에 따라 달라집니다.
프로그래머로서, 우리는 어떻게 이 모든 정보를 따라가서 우리의 응용 프로그램에 전달합니까?나는 그 프로그램이 없는 프로그램을 만들었는데, 자신이 도처에서 도구와 상태를 전달하고 있다는 것을 발견했다.코드가 너무 많아서 모든 코드의 진도를 따라잡기가 매우 어렵다.그 경험은 매우 좋았다.물론, 그것은 나로 하여금 Redux 기술 (그리고 Redux Context 을 갈망하게 한다. 이것 좀 봐.Redux는 이러한 모든 것을 관리하고 단순화합니다.

덮개 아래:
연결된 구성 요소에서 Redux 저장소에 직접 접근할 수 없습니다. "React Redux"라이브러리를 가져와야 합니다.이렇게 하면 우리는 아래의 두 가지 함수인 맵StateToProps와 맵DispatchToProps에 접근할 수 있다.
import { connect } from react-redux
그리고 보통 구성 요소의 밑에
const mapStateToProps = state => {
    return {
        stateItemToUse: state.reducer.stateItem
    }
}
const mapDispatchToProps = dispatch => {
    return {
        actionToDispatch: () => ({ type: 'DISPATCH TYPE', action: action})
    }
}
export default connect(mapStateToProps, mapDispatchToProps)(componentName)
이것은 구성 요소 내부의 저장소에 접근할 수 있도록 합니다. 이 저장소를 사용하여 작업을 스케줄링하고 Redux 저장소에 기록하며 상태를 업데이트하거나, 저장소의 상태 데이터에 접근해서 구성 요소 논리에서 사용할 수 있습니다.

THUNK 소개

"Redux Thunk is a middleware that lets you call action creators that return a function instead of an action object. That function receives the store’s dispatch method, which is then used to dispatch regular synchronous actions inside the body of the function once the asynchronous operations have completed."

Asynchronous Redux Actions Using Redux Thunk

"Redux-Thunk is a middleware that allows our action creators to return a function instead of an action object. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. It looks at every action that passed thrugh the system; and if it’s a function, it calls that function. This is just another tool that can help us decouple our application logic from our view rendering."

Front End Curriculum



왜 펑?
간단한 작은 응용 프로그램에 대해서는 이렇게 할 필요가 없을 수도 있다.여러 가지 방법으로 관리할 수 있지만 Thunk의 하이라이트는 응용 프로그램의 복잡성과 규모가 커지면서 편리함을 제공한다는 데 있다.

  • 비동기 스케줄링
    우리는 보통 데이터를 가져와서 Redux 저장소에 저장하기를 원하지만 디스패치는 비동기 약속을 어떻게 처리하는지 모른다.계속해서 주목해 주십시오. 제가 Thunk 전후로 어떻게 했는지 보실 수 있을 것입니다.

  • 구성 요소가 간단하고 표현에 집중(추상 논리)
    API 호출, 디스패치 및 관련 논리를 구성 요소에서 추상화하여 구성 요소에 적용할 수 있습니다.서비스 또는 서비스/행동

  • 마른 거!! -코드 중복
    Google의 로그인, 등록 구성 요소와 다른 구성 요소는 유사한 절차를 따라 사용자를 로그인시키고 프로그램의 수분을 보충할 수 있습니다.나는 몇 군데에서 반복된 코드부터 시작했다.Thunk을 사용하면 유사한 가져오기를 하나의 action creator 함수에 조합하여 위 구성 요소에서 사용할 수 있습니다.

  • 코드, 오류 및 유지 관리 지점 감소
    한 곳에서 한 번에 물건을 찾거나 그 다음에 발송하는 것이지, 몇 군데에서 ==의 큰 개선이 아니다.

  • 기능 순도
    Redux 상태 관리의 핵심 원칙은 순수한 기능의 기초 위에서 세워지고 순수한 기능을 둘러싸고 있다는 것이다.API 호출의 연쇄 반응은 이 원칙에 어긋나 오히려 의존 관계와 구성 요소 간의 더욱 긴밀한 결합을 일으켰다.이것은 우리의 코드를 더욱 테스트하고 추리하기 어렵게 한다.

  • 어셈블리 결합:
    응용 프로그램이 증가함에 따라, 지루하고, 상세하며, 상세한 수령과, 응용 상점에 대한 맞춤형 분배는 우리의 구성 요소를 다시 사용하거나 마운트 해제하기 더욱 어려워진다.주입과 반전 제어에 의존하는 개념을 알게 해 주셔서 감사합니다Sandi Metz.나는 그녀의 책을 극력 추천한다.

  • API의 일관성:
    다음을 고려합니다Full Stack Academy.
    > 우리는 이 모든 것을 피할 수 있다. 저장만 하면 된다.비동기 처리 프로그램에서 스케줄링...
    >javascript > // in an action creator module: > import store from '../store' > > const simpleLogin = user => ({ type: LOGIN, user }) > > const asyncLogin = () => > axios.get('/api/auth/me') > .then(res => res.data) > .then(user => { > store.dispatch(simpleLogin(user)) > }) > > // somewhere else in our component: > asyncLogin() >
  • But now our components sometimes call store.dispatch(syncActionCreator()), and sometimes call doSomeAsyncThing().

    • In the latter case, it’s not obvious that we are dispatching to the store. We cannot identify Redux actions at a glance, making our app’s data flow more opaque.
    • What if we later change an action-function from sync to async, or async to sync? We have to track down and modify the call site for that function, in every single component it is used. Yuck!


    내 애플리케이션의 프로세스 예:
    다음은 Thunk을 재구성하여 구현한 방법입니다.
    사용자가 등록하고 백엔드에서 영패를 받습니다.만약 사용자가 영패를 받게 된다면, 우리는 다시 한 번 (fetchData) 프로그램을 시작하는데 필요한 모든 기본 데이터로 프로그램을 보충할 것입니다.우리는 같은 사용자가 지금 이 영패를 사용하여 로그인하는 것을 원하지 않는다.그들이 성공적으로 등록되었을 때, 우리는 그들도 로그인할 수 있기를 바란다.그러나 기존 사용자가 로그인할 때 사용자가 신분 검증을 거쳤을 때도 완전히 같은 상황이 발생할 수 있다.우리는 데이터를 가져와 이 사용자의 세션에 프로그램을 추가합니다.그리고 이 사용자가 페이지를 새로 고칠 때마다, 우리는componentDidMount 갈고리를 사용하여 같은 데이터를 얻는다.
    이 모든 것은 일리가 있지만, 내가 처음 통과한 후, 나는 몇 개의 구성 요소 중 적어도 20줄의 중복 코드를 가지고 이 일을 완성했다.따라서 응용의 전체 생명 주기 중 80줄의 중복 코드와 몇 군데는 유지보수가 필요할 수 있다.더군다나 이 구성 요소들 중에는 논리적 혼란이 많다.내가 어떻게 나를 엉망으로 만들었지!?!나는 곧 이 코드가 틀렸다는 것을 맡을 수 있는데, 나는 어떻게 그것을 복구하는지 알고 싶다.그 점에서 나는 시간제한 아래 MVP가 생겼고, 나는 Thunk 같은 중간부품에 대해 아무것도 모른다.

    재구성
    다음은 로그인 구성 요소에서 사용하기 시작한 내용입니다.이 글의 마지막 부분에서, 나는 Thunk를 사용하여 전체 캡처와 모든 동작 스케줄링을 추출할 것이다.
    import React from 'react';
    import { connect } from 'react-redux'
    import { withRouter } from 'react-router';
    import { API_ROOT} from '../services/apiRoot'
    
    handleLogin = token => { //this 
        localStorage.setItem('auth_token', token);
        localStorage.setItem('userType', this.props.userType);
        this.props.setLoginStatus(true)
    
        fetch(`${API_ROOT}/app_status`, fetchObj)
          .then(res => res.json())
          .then(appData => {
            props.storeUserJobs(appData.jobs)
            props.storeUserData(appData.user)
            if (userType === 'employer') {
              props.storeUserFavorites(appData.employer_favorites)
              props.storeAuthoredReviews(appData.employer_reviews)
              props.storeReviewsAboutMe(appData.caregiver_reviews)
              props.storeCaregivers(appData.caregivers)
            } else if (userType === 'caregiver') {
              props.storeUserFavorites(appData.caregiver_favorites)
              props.storeAuthoredReviews(appData.caregiver_reviews)
              props.storeReviewsAboutMe(appData.employer_reviews)
              props.storeEmployers(appData.employers)
              props.storeAvailableJobs(appData.available_jobs)
              props.storeInterestedJobs(appData.interested_jobs)
            } else { console.log('No userType specific appData stored') }
            props.hydrateComplete()
          })
          .catch(error => console.log(error))
    }
    
    그것은 매우 길다. 나는 안다.저는 공부하고 있습니다:) 어쨌든 맵디스패치ToProps 기능을 제공합니다. 이 기능에 모든 조작을 설정합니다.나는 우리가 이해했다고 생각한다.이것은 너무 많은 물건이어서 하나의 구성 부분에서 생활할 수 없으며, 몇 가지는 말할 것도 없다.

    Thunk 설정
    Thunk을 먼저 설정하려면 "사선 추가 @reduxjs/toolkit"를 실행해야 합니다.
  • 만약 당신이 이렇게 하는 것이 레드스 코어를 얻기 위해서라면 당신은 아주 좋습니다.없는 경우 Redux 애플리케이션에 이 키트를 사용하고 Thunk을 사용하는 것이 좋습니다.
    다음은 상점에서 다음과 같은 일을 해야 합니다.js:
    입력한 내용을 주의하세요."compose"는 "apply Middleware"인자와createStore 함수 중의 REDUX DEVTOOLS를 확장해서 조합할 수 있도록 합니다.
  • import { combineReducers, compose, createStore, applyMiddleware } from 'redux';
    import thunk from 'redux-thunk'
    
    export default createStore(
      rootReducer,
      compose( applyMiddleware(thunk), window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__({trace: true}))
    );
    
    그리고 나는 이 폴더에 이 파일을 만들었다. src/actions/fetches.js
    import { API_ROOT } from '../services/apiRoot'
    
    export const fetchData = (userType) => {
        const auth_token = localStorage.getItem('auth_token')
        const fetchObj = {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            'Auth-Token': auth_token,
          }
        }
        return (dispatch) => {
            dispatch({ type: 'LOADING_DATA' })
            fetch(`${API_ROOT}/app_status`, fetchObj)
            .then(res => res.json())
            .then(appData => {
                dispatch({ type: 'STORE_USER_JOBS', userJobs: appData.jobs })
                dispatch({ type: 'STORE_USER_DATA', userData: appData.user })
                if (userType === 'employer') {
                    dispatch({ type: 'STORE_USER_FAVORITES', userFavorites: appData.employer_favorites })
                    dispatch({ type: 'STORE_REVIEWS', authoredReviews: appData.employer_reviews })
                    dispatch({ type: 'STORE_REVIEWS_ABOUT_ME', reviewsAboutMe: appData.caregiver_reviews })
                    dispatch({ type: 'STORE_CAREGIVERS', caregivers: appData.caregivers })
                } else if (userType === 'caregiver') {
                    dispatch({ type: 'STORE_USER_FAVORITES', userFavorites: appData.caregiver_favorites })
                    dispatch({ type: 'STORE_REVIEWS', authoredReviews: appData.caregiver_reviews })
                    dispatch({ type: 'STORE_REVIEWS_ABOUT_ME', reviewsAboutMe: appData.employer_reviews })
                    dispatch({ type: 'STORE_EMPLOYERS', employers: appData.employers })
                    dispatch({ type: 'STORE_AVAILABLE_JOBS', availableJobs: appData.available_jobs })
                    dispatch({ type: 'STORE_INTERESTED_JOBS', interestedJobs: appData.interested_jobs })
                } else { console.log('No userType specific appData stored') }
                dispatch({ type: 'FINISH_LOADING' })
            })
            .catch(error => console.log(error))
        }
    }
    
    주의해야 할 점:
  • Action creator fetchData가 함수를 반환합니다.
  • 전형적인 Redux 동작 창설자는 ({type:type, action:action}) 의 대상을 되돌려줍니다.Thunk과 new
  • 입니다.
  • 이 함수는 매개 변수와 사용자 유형으로 전달
  • 함수 비동기 획득 데이터
  • 이 작업을 만든 사람이 첫 번째로 해야 할 일은'로드 데이터'를 보내는 것입니다.
    상태가 설정됩니다.로드: 예.이 함수가 완성되면 가져온 데이터를 저장소에 불러올 때 상태는 입니다.불러오기가false로 전환되어 현재 수화 프로그램의 멋진 리셋을 터치합니다.
  • 우리는 연결 구성 요소에서처럼 도구에 비치는 분배를 사용하지 않고 전송된 분배 함수를 사용하여 조작을 저장소에 분배한다.

  • 로그인으로 돌아갑니다.js...
    맵 StateToProps의 동작 할당, 그리고 맵 StateToProps의 일부 항목을 재구성했습니다.
    handleLogin = token => {
    localStorage.setItem('auth_token', token);
    localStorage.setItem('userType', this.props.userType);
    this.props.setLoginStatus(true)
    this.props.fetchData(this.props.userType) // a thing of beauty to me
    }
    

    요약
    이 구성 요소(editUser, login 등)의 모든 가져오는 것을 계속 재구성합니다.나는 나의 구성 요소 밖에서 나의 리셋을 통합시켜서 매우 기쁘다.이제 그들의 일, 읽기와 추리는 훨씬 간단해졌다.그것들과fetch의 결합도 그다지 긴밀하지 않아fetch의 논리와 스케줄에 대해서도 잘 모른다.연결된 구성 요소에서 거의 모든 MapToprop을 삭제할 수 있습니다.

    약속의 유용한 링크

  • Thunks in Redux 가브리엘 러베크

  • Stack Overflow: Why do we need middleware for async flow in Redux?단 아브라모프
  • 응답

  • Stack Overflow: Dispatching Redux Actions with a Timeout단 아브라모프
  • 응답

    좋은 웹페이지 즐겨찾기