2016-06-10 3 views
0

초보자 질문에 대한 감속기 대 액션. From redux documentation :redux reducer 대 액션

작업 뭔가 일이 있다는 사실을 설명하지만, 응답 방법 응용 프로그램의 상태 변경을 지정하지 마십시오.

과 같은 인수를 감안할 때

, 감속기는 다음 상태를 계산해야하며 반환 . 놀라움이 없습니다. 부작용이 없습니다. API 호출이 없습니다. 돌연변이가 없습니다. 그냥 계산.

  1. 사용자가지도에 점을 배치하고 그 지점 사이의 경로를 얻을 수 있습니다 :

는 그래서 우리는 다음과 같은 시나리오를 고려합니다.

  • 사용자가지도를 처음 클릭 할 때 이것이 출발점입니다. 그가 두 번째로 클릭 할 때 - 이것은 그의 마지막 포인트입니다. 연속 클릭은 이전 포인트와 끝 위치 사이에 포인트를 추가합니다.
  • 각 점을 추가 한 후 (첫 번째 점 제외) 경로를 새 점과 이전 점 사이에서 계산해야합니다. 그래서 S -> A -> F가 있고 B 점 (S -> A -> B - F)을 더하면 A -> B와 B -> F가 계산되어야합니다.
  • 그래서

    • 새로운 점은
    • 새로운 경로가 마침 점으로 계산해야 목록의 마지막에 있지 배치 : 모든 3+ 점을 추가에 따라 두 가지 부작용이있다.

    나는이 나의 포인트 구조를 모델링하는 경우 : 나에게

    // pseudo code 
        export function addMapPoint(newPoint) { 
         return (dispatch, getState) => { 
         const {points} = getState(); 
         const position = getInsertPosition(points, newPoint) 
         dispatch(addPoint(newPoint, position)); 
         if (points.length >= 2) { 
          const previousPoint = getPreviousPoint(points, position); 
          calculateRoute(newPoint, previousPoint).then(route => { 
          dispatch(updateRoute(newPoint, route)) 
          }) 
         } 
         } 
        } 
    

    이 어떻게 든 모순 :

    // typescript 
    interface Point { 
        coordinates; 
        routeTo?; 
    } 
    

    내가 항목의 위치 계산과 작업의 경로 검색, 예를 수행하기 위해 수정 있습니까 "하지만 응용 프로그램의 상태가 어떻게 변하는 지 지정하지 마십시오."- 작업에서 새 지점을 삽입 할 위치를 지정했기 때문입니다.
    나는 감속기에서 삽입 위치를 계산할 수 있었지만, 마침 지점에 대한 경로 데이터를 어떻게 가져 옵니까?
    올바른 접근 방법은 무엇입니까?

    답변

    1

    두 개의 점을 받아들이고 그 사이의 경로를 해결 한 약속을 반환한다고 가정하면 calculateRoute 함수가 있다고 가정합니다.사용자 후, 이제

    let reducer = (state = { points: [] }, action) => { 
        switch (action.type) { 
         case 'ADD_POINT': 
          return Object.assign({}, state, { 
           points: [ 
            ...state.points.slide(0, action.index), 
            action.point, 
            ...state.points.slide(action.index + 1) 
           ] 
          }); 
         default: 
          return state; 
        } 
    } 
    

    :의는 감속기에서이 작업을 처리 할 수 ​​있도록,

    let addPoint = (point, index) => { 
        return { 
         type: 'ADD_POINT', 
         point: point, 
         index: index 
        } 
    } 
    

    을 다음 :

    먼저, 그래서 우리는 우리의 포인트가 제대로 저장되어 알고 간단한 행동 작성자를 만들 수 포인트를 추가하면 addPoint을 사용하여 액션을 만들고 여기까지 발송합니다. 그러나 이것은 쉬운 일입니다.

    내가 위해 노력 구조는 너무 내 감속기의 경로 목록을 가지고, 그래서 그 지원을 확장 할 수 있도록하는 것입니다

    :

    let reducer = (state = { points: [], routes: [] }, action) => { 
        switch (action.type) { 
         case 'ADD_POINT': 
          return Object.assign({}, state, { 
           points: [ 
            ...state.points.slide(0, action.index), 
            action.point, 
            ...state.points.slide(action.index + 1) 
           ] 
          }); 
         case 'UPDATE_ROUTES': 
          return Object.assign({}, state, { 
           routes: action.routes 
          }); 
         default: 
          return state; 
        } 
    } 
    

    그리고 행동 작성자가 될 것입니다 :

    let updateRoutes = (routes) => { 
        return { 
         type: 'UPDATE_ROUTES', 
         routes: routes 
        } 
    } 
    

    를하시기 바랍니다 우리가 전체 라우트 콜렉션을 무시하고 있음을 주목하십시오. 지금은 괜찮습니다.하지만 프로덕션 시스템에서는 조금만 최적화하고 싶을 것입니다.

    이제 우리는 실제로 어떤 논리를 작성해야합니다. 우리는 점 집합을 얻는 calculateRoutes이라는 편리한 가정을 가정하고 각 경로의 목록을 해결하는 약속을 반환하며, 각 경로는 두 점과 실제 경로를 포함하는 개체입니다. 우리 thunk 지금과 같이 표시됩니다 그런 말로 미루어 보아 :

    내 의견 방법 좋네요
    addPointAndUpdateRoutes = (point, index) => { 
        return (dispatch, getState) => { 
         // First, update the point list 
         dispatch(addPoint(point, index)); 
    
         // Now, recalculate routes 
         calculateRoutes(getState().points) 
          .then(routes => dispatch(updateRoutes(routes)); 
        }; 
    }; 
    

    .


    이제 오프 물론이 최적화 된 방식으로이 기능을 구현하는 매우 어려운 작업이 아니다하지만 우리가 마법의 calculateRoutes 함수는 심각한 가정 아니다 있다고 가정 (실제로 의미하는 것이 유일한 루트 서버를 보내 우리 전에 계산하지 않았다 등). BUT 이것은 단지 로직이며 이 아니므로 상점 및 감속기에서 정의한 "계약"을 유지하는 한 원하는대로 구현할 수 있습니다.

    희망이 도움이됩니다.

    +0

    그래서 제안 된'addPointAndUpdateRoutes = (point, index)'와'addPoint (point, index)'시그니처를 살펴보면 인덱스 계산이 ui? 하지만 좌표를 수동으로 입력하는지도를 클릭하면 포인트를 추가 할 수 있습니까? 'calculateRoutes'에 대해서는 100 점이 있다면? 아니면 200? 매시간 전체 목록을 반복하면서 일부 캐시 (다른 상태 ...)를 확인하고 사용자가 항상 처음부터 시작할 수 있는지 확인하십시오. 그때 나는 그 캐시를 무효화해야합니다. – gerasalus

    +0

    UI에서'index'를 계산할 수 있다고 생각합니다. 기존의 두 점 사이에 점을 추가하는 것은 UI에서 매우 명확하게 표현 될 수있는 것입니다. 'calculateRoutes'에 대해서 - 이미 계산 된 경로라면 즉시 반환 할 것입니다.이 구현은 클라이언트와 서버에 있어야합니다. 사용자의 점수가 100 또는 1000 또는 5000 점인 경우에는 별 문제가되지 않으며 실제로 계산되지 않는 한 매우 빠르게 발생합니다. 어쨌든 100 점을 지원한다면 UI 구현에 관계없이 점수를 계산해야합니다. –

    +0

    잘 요점은 내가 포인트를 추가 할 수있는 2, 4 또는 5 개의 다른 장소를 가질 수 있다는 것이 었습니다. 그리고 논리는 동일하게 유지됩니다 - 첫 번째 점 - 추가, 두 번째 - 추가, 세 번째 - 마지막 점 추가 이전 등.이 논리는 각 UI 구성 요소에서 중복되지 않아야합니다. 내가 스마트 calculateRoutes 접근 방식을 사용하는 경우 이것은 감속기에서 할 수 있습니다 (하지만 맞습니까?).또는 왜 내가 별도로 경로를 저장해야합니까 - 그들은 요점없이 살 수 없습니다. 또한 마침 지점에 도달 할 수없는 부작용을 유발하는 도달 할 수없는 지점에는 경로가 없을 수 있습니다. – gerasalus

    관련 문제