2017-10-15 7 views
1

구독 및 실시간 업데이트에 대한 일반적인 접근 방식을 이해하려면 도움이 필요합니다. 나는 React Native 앱을 가지고 있고 Apollo와 Graphcool 서비스를 백엔드로 사용하고 있습니다.React 앱에서 구독 방법에 접근하는 방법

앱을 보는 사용자가 변경된 내용의 푸시 알림을받는 시나리오가 몇 가지 있습니다. 당연히 화면 데이터도 업데이트되어야합니다. 서브 스크립 션은 그 직업에 대한 확실한 후보자이며 본질적으로 작동하도록했습니다.

Google지도에서 플레이어 아바타를 배치하는 데 사용되는이 구독과 같이 잘 작동합니다.

subscription PlayerMap($gameId: ID) { 
    Game(filter: { mutation_in: [CREATED, UPDATED], node: { id: $gameId } }) { 
    node { 
     players { 
     id 
     character { 
      id 
      name 
     } 
     user { 
      id 
      latitude 
      longitude 
     } 
     } 
    } 
    } 
} 

은 그런 물건을 업데이트하려면이 쿼리를 실행 (단순성) 아폴로에서 refetchQueries와 함께 돌연변이 createPlayer을 실행하는 다른 응용 프로그램 화면이 있습니다. 이 완료 이제 때

query GameCharacters($gameId: ID!) { 
    Game(id: $gameId) { 
    players { 
     id 
     character { 
     id 
     name 
     } 
    } 
    } 
} 

, 구독 쿼리 (즉, 다른 화면에 활성 상태)도 업데이트됩니다 있지만 어떤 이유로 전체 Game 노드는 data 개체에 없습니다.

구독을 처리 할 때 이와 같은 구성 요소가 있습니다.

class Subscriber extends Component<void, Props, void> { 
    componentDidMount() { 
    this.subscribe() 
    } 
    componentWillReceiveProps({ data, shouldResubscribe }) { 
    if (this.unsubscribe) { 
     if (shouldResubscribe && shouldResubscribe(data, this.props.data) !== true) { 
     return 
     } 
     this.unsubscribe() 
    } 
    this.subscribe() 
    } 
    subscribe() { 
    const { data, query, variables } = this.props 
    this.unsubscribe = data.subscribeToMore({ 
     document: query, 
     variables, 
    }) 
    } 
    unsubscribe: ?Function = null 
    render() { 
    return this.props.children(this.props.data) 
    } 
} 

다음과 같이 render prop 패턴을 사용하면됩니다.

const OrgMapScreen = ({ gameId, data: initialData }: Props) => (
    <Subscriber 
    data={initialData} 
    query={OrgMapSubscription} 
    variables={{ gameId }} 
    shouldResubscribe={(nextData, prevData) => nextData.Game !== prevData.Game} 
    > 
    {({ Game }) => { 
     const markers = Game.players.map(makePlayerMarker) 
     return <MapScreen mapProps={{ markers }} /> 
    }} 
    </Subscriber> 
) 

나는 왜 그런 일이 일어나고 있는지 혼란 스럽다. 그런 것들을 어떻게 처리 할 것인가? 아마도 refetchQueries 대신 GameCharacters에 대한 다른 가입을 설정해야합니까?

답변

2

내가 아폴로 전문가가 아니라고 추측해야한다면, document 입력이 subscribeToMore에 잘못 입력되었다고 추측 할 수 있습니다 (매개 변수로 구독이 아닌 쿼리를 사용하고있는 것 같습니다.)이거나 updateQuery이 누락되어 subscribeToMore에 있으면 업데이트 된 데이터가 반환됩니다.

여기에는 Order의 변경 사항을 수신하는 orderChanged 구독이 있습니다. 업데이트를 받으면 orders 검색어의 주문을 업데이트 된 주문으로 대체하려고합니다. 당신은 최소한의 가능한 REPO로 날을 제공 할 수있는 경우

componentDidMount() { 
    this.props.data.subscribeToMore({ 
    document: OrderSubscription, 
    variables: { 
     range: [0, 25] 
    }, 
    updateQuery: (prev, { subscriptionData, }) => { 
     // If no subscription data is passed, just return the previous 
     // result from the initial `orders` query 
     if (!subscriptionData.data) return prev 

     // get the data for the updated order from the subscription 
     const updatedOrder = subscriptionData.data.orderChanged 

     // find the index of the updated order from within the existing 
     // array of orders from the `orders` query 
     const existingOrderIndex = prev.orders.findIndex(order => (order.id === updatedOrder.id)) 

     // guard for missing data 
     if (existingOrderIndex) { 
     // replace the old order with the updated order 
     prev[existingOrderIndex] = updatedOrder 
     // return orders with new, updated data 
     return prev 
     } 

     return prev 
    }, 
    }) 
} 

것은, 내가 통해 작동 드리겠습니다 : 우리는 subscribeToMoreupdateQuery 기능에 그렇게 (오타에 대한 사과, 이것은 정확한 복사 - 붙여 넣기되지 않습니다) 너와 함께. 지난 주 대부분을 구독을 통해 보냈다.

+0

그래,'updateQuery'가 필요하다는 것이 밝혀졌습니다. 나는 왜 Apollo가 유형과'dataIdFromObject'를 기반으로 자체 스토어와 업데이트 스토어에서 결과를 크롤링 할 것이라는 인상을 받았는지 모르겠습니다. 오 잘. 광산과 같이 깊게 중첩 된 구조에'불변 헬퍼 (immutable-helper) '를 사용해야했지만 지금은 효과가있는 것처럼 보입니다. 감사 – FredyC