2016-07-01 3 views
5

Normalizr은 엔티티의 구조화 된 JSON 리포지토리를 만드는 데 유용합니다.Redux normalizr + 감소 된 응답 처리

많은 경우에 데이터 목록을 표시합니다. posts이 정규화되었습니다. posts이 나열된 경우 API 응답은 몇 가지 주요 필드로 제한됩니다.

posts 중 하나를 표시하는 경우도 있지만 모든 필드가 포함 된 API에서 FULL JSON 엔티티를 가져와야합니다.

어떻게 처리해야합니까?

별도의 감속기, 썽크/사가, 선택기 및 동작?

API에서 가져온 post 확장 버전을 간단히 삽입하십시오. 전에 선택기 등을 재사용?

답변

5

데이터베이스의 앱 상태를 생각해보십시오. 우리는 응답 데이터를 정상화하고 작업을 파견하는 성공 응답 후

// schemas.js 
import { Schema, arrayOf } from 'normalizr'; 

const POST = new Schema('post'); 
const POST_ARRAY = arrayOf(POST); 

: 우리는 우리의 normalizr 스키마를 작성하는 모든

{ 
    entities: { 
    // List of normalized posts without any nesting. No matter whether they have all fields or not. 
    posts: { 
     '1': { 
     id: '1', 
     title: 'Post 1', 
     }, 
     '2': { 
     id: '2', 
     title: 'Post 2', 
     } 
    }, 
    }, 
    // Ids of posts, which need to displayed. 
    posts: ['1', '2'], 
    // Id of full post. 
    post: '2', 
} 

첫째, 나는 당신이이 상태 모양을 사용하는 것이 좋습니다

// actions.js/sagas.js 
function handlePostsResponse(body) { 
    dispatch({ 
    type: 'FETCH_POSTS', 
    payload: normalize(body.result, POST_ARRAY), 
    }); 
} 

function handleFullPostResponse(body) { 
    dispatch({ 
    type: 'FETCH_FULL_POST', 
    payload: normalize(body.result, POST), 
    }); 
} 

감속기에서는 entities 감속기를 만들어야 모든 작업을 청취 할 수 있으며 지불 할 금액은 entities입니다. 부하, 응용 프로그램 상태로이 개체를 추가 :

// reducers.js 
import merge from 'lodash/merge'; 

function entities(state = {}, action) { 
    const payload = action.payload; 

    if (payload && payload.entities) { 
    return merge({}, state, payload.entities); 
    } 

    return state; 
} 

는 또한 우리는 감속기가 FETCH_BOARDSFETCH_FULL_BOARD 작업을 처리하기 위해 해당 만들어야합니다

// Posts reducer will be storing only posts ids. 
function posts(state = [], action) { 
    switch (action.type) { 
    case 'FETCH_POSTS': 
     // Post id is stored in `result` variable of normalizr output. 
     return [...state, action.payload.result]; 
    default: 
     return state; 
    } 
} 

// Post reducer will be storing current post id. 
// Further, you can replace `state` variable by object and store `isFetching` and other variables. 
function post(state = null, action) { 
    switch (action.type) { 
    case 'FETCH_FULL_POST': 
     return action.payload.id; 
    default: 
     return state; 
    } 
} 
+0

질문이 있습니다. '병합 ({}, 상태, payload.entities);'상태를 변경 하시겠습니까? – Daskus

+0

@Daskus 아니요. 빈 객체를 첫 번째 인수로 전달할 때 merge 함수가 새 객체를 반환합니다. – 1ven

+0

이것은 가장 좋은 대답입니다. 우리는이 접근법을 위해 정확하게 끝을 맺었습니다. 열쇠는 훌륭한 셀렉터와 필터를 작성하는 데 있습니다. 또한 Immutable JS를 사용하는 것이 좋습니다 ...! – AndrewMcLagan

1

나는 당신의 두 가지 선택 모두 동의를하고있는 것 같은 결론에 도달하십시오. 그러나의이 이상을 장점 양식을 볼 수있는 그들에 대해 자세히 살펴보기로하자 다른 :

(B) 당신은 당신의 감속기에 하나의 엔티티로 포스트 엔티티 (미리보기 및 전체 표현)을 병합 할 수 있습니다,하지만 당신은 유지하는 것 트랙을 result 배열 (미리보기 및 전체 표현)로 가져오고, API 요청 후 normalizr 정규화 데이터에서 가져옵니다. 그런 다음 게시물의 전체 표현을 이미 가지고 있다면 쉽게 구분할 수 있습니다. 귀하의 하위 상태는 다음과 같습니다

const postState = { 
    // merged results from PREVIEW api 
    previews: [1, 2, 3], 

    // merged results from FULL api 
    full: [2], 

    // all merged entities 
    entities: { 
    1: { 
     title: 'foo1' 
    }, 
    2: { 
     title: 'foo2', 
     body: 'bar', 
    }, 
    3: { 
     title: 'foo3' 
    } 
    } 
}; 

(A) 당신은 개체를 구별하는 방법은 두 감속기 + 행동, 각각의 표현 하나를 것. PREVIEW 또는 FULL 게시물 API 요청에 따라 하나의 명시 적 조치를 통해 귀하의 감속기 중 하나를 제공하게됩니다. 귀하의 하위 상태는 다음과 같습니다 매우 높은 수준의 관점에서

const previewPostState = { 
    // merged results from PREVIEW api 
    result: [1, 2, 3], 

    // all preview entities 
    entities: { 
    1: { 
     title: 'foo1' 
    }, 
    2: { 
     title: 'foo2', 
    }, 
    3: { 
     title: 'foo3' 
    } 
    } 
}; 

const fullPostState = { 
    // merged results from FULL api 
    result: [2], 

    // all full entities 
    entities: { 
    2: { 
     title: 'foo2', 
     body: 'bar' 
    } 
    } 
}; 

당신은 이미 중복 된 정보를 저장해야 볼 수 있습니다.id: 2의 게시 엔티티는 title 속성으로 두 번 저장됩니다. 한 번은 previewPostState이고 한 번만 fullPostState이됩니다. 전역 상태에서 title 속성을 변경하려면 두 위치에서 수행해야합니다. 하나는 Redux에서 진실의 단일 소스를 침해합니다. 그것이 내가 선택과 함께 갈 이유입니다. (B) : 게시물 엔티티를위한 장소가 하나 있지만 결과 배열에 의해 그 표현이 명확하게 구별 될 수 있습니다.