1. 7달 전

    36 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.78 ~ 2.80

  2. 7달 전

    35 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.75 ~ 2.77

  3. 7달 전

    34 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.70 ~ 2.74

  4. 7달 전

    33 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.68 ~ 2.69

  5. 7달 전

    32 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.66 ~ 2.67

  6. 7달 전

    31 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.61 ~ 2.65

  7. 7달 전

    30 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.57 ~ 2.60

  8. 7달 전

    29 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.54 ~ 2.56

  9. 7달 전

    28 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.51 ~ 2.53

  10. 7달 전

    27 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.46 ~ 2.50

  11. 7달 전

    26 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.44 ~ 2.45

  12. 8달 전

    25 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.41 ~ 2.43

  13. 8달 전

    24 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.39 ~ 2.40

  14. 8달 전

    23 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.36 ~ 2.38

  15. 8달 전

    22 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.31 ~ 2.35

  16. 8달 전

    21 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.22 ~ 2.25

  17. 8달 전

    20 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.22 ~ 2.25

  18. 8달 전

    19 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.18 ~ 2.21

  19. 8달 전

    18 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.13 ~ 2.17

  20. 8달 전

    17 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.7 ~ 2.12

  21. 9달 전

    16 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 2.0 ~ 2.6

  22. 9달 전

    15 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.81 ~ 1.87

  23. 9달 전

    14 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.76 ~ 1.80

  24. 9달 전

    13 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.72 ~ 1.75

  25. 9달 전

    12 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.64 ~ 1.71

  26. 9달 전

    11 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.60 ~ 1.63

  27. 9달 전

    10 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.56 ~ 1.59

  28. 9달 전

    9 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.49 ~ 1.55

  29. 9달 전

    8 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.40 ~ 1.48

  30. 9달 전

    7 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.34 ~ 1.38

  31. 9달 전

    6 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.26 ~ 1.32

  32. 10달 전

    5 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.22 ~ 1.25

  33. 10달 전

    4 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.17 ~ 1.21

  34. 10달 전

    3 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.12 ~ 1.16

  35. 10달 전

    2 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.8 ~ 1.11

  36. 10달 전

    1 우버 클론 코딩 (nomad coders)

    우버 코딩 강의 로그 1.1 ~ 1.7

Tamm자바스크립트 웹 개발 환경을 좋아하고 사람들에게 재미를 주는 것에 관심이 많은 개발자 입니다.

35 우버 클론 코딩 (nomad coders)

우버 코딩 강의 로그 2.75 ~ 2.77

featured image thumbnail for post 35 우버 클론 코딩 (nomad coders)

이 포스트는 nomad coders의 우버 클론 코딩 시리즈를 듣고 정리한 글 입니다.

https://academy.nomadcoders.co/p/nuber-fullstack-javascript-graphql-course

#2.75 Ride Status Subscription

이전에 운전자가 버튼을 눌러서 상태를 업데이트 하도록 했다. 이 상태 업데이트를 운전자, 승객 모두 subscription하도록 해보자.

  • src/routes/Ride/Ride.queries.ts RIDE_SUBSCRIPTION 을 정의하고 yarn codegen을 하자.

    ...
    export const RIDE_SUBSCRIPTION = gql`
      subscription rideUpdate {
        RideStatusSubscription {
          id
          status
          pickUpAddress
          dropOffAddress
          price
          distance
          duration
          driver {
            id
            fullName
            profilePhoto
          }
          passenger {
            id
            fullName
            profilePhoto
          }
          chatId
        }
      }
    `;
    
  • src/routes/Ride/RideContainer.tsx RideQuery

    import { SubscribeToMoreOptions } from 'apollo-client';
    import React from 'react';
    import { Mutation, Query } from 'react-apollo';
    import { RouteComponentProps } from 'react-router-dom';
    import { USER_PROFILE } from '../../sharedQueries.queries';
    import { 
      getRide, 
      getRideVariables, 
      updateRide,
      updateRideVariables,
      userProfile 
    } from '../../types/api';
    import { GET_RIDE, RIDE_SUBSCRIPTION, UPDATE_RIDE_STATUS } from './Ride.queries';
    import RidePresenter from './RidePresenter';
    
    ...
        return (
          <ProfileQuery query={USER_PROFILE}>
            {({ data: userData }) => (
              <RideQuery query={GET_RIDE} variables={{ rideId: parseInt(rideId, 10) }}>
                {({ data: rideData, loading, subscribeToMore }) => {
                  const subscribeOptions: SubscribeToMoreOptions = {
                    document: RIDE_SUBSCRIPTION
                  }
                  subscribeToMore(subscribeOptions);
                  return (
                    <RideUpdate 
                      mutation={UPDATE_RIDE_STATUS}
                      refetchQueries={[{ query: GET_RIDE , variables: { rideId: parseInt(rideId, 10) }}]}
                    >
                      {updateRideMutation => (
                        <RidePresenter 
                          rideData={rideData}
                          userData={userData}
                          updateRideMutation={updateRideMutation}
                        />
                      )}
                    </RideUpdate>
                  )
                }}
              </RideQuery>
            )}
          </ProfileQuery>
        )
      }
    }
    
    export default RideContainer;
    

이번에는 Ride를 db에서 삭제 후 user.isRiding, user.isTaken false로 바꾼 후 Ride 요청부터 운전자의ACCEPTED 이후의 단계까지 계속 진행해보자. 깔끔하게 동작한다.

subscribeOptions 을 subscribeToMore 할 때 HomeContainer에서는 updateQuery를 정의해서 prev에 값을 엎어쓰도록 했는데 여기서는 별도의 updateQuery를 작성하지 않았다. 그 이유는 Ride.queries.ts 에 정의된 GETRIDE의 결과와 RIDESUBSCRIPTION의 결과가 동일하기 때문이라고 한다. (이건 니콜라스의 생각, 확인이 필요)

또 RideQuery에서 subscription 해서 ride를 업데이트 하는데, 운전자가 RideUpdate해서 refetchQueries에 정의된것처럼 업데이트를 한다. 이렇게 하면 두번 중복되는것 아닐까? 하고 생각했다.

#2.76 Ride Status Subscription part Two

운전자가 FINISH 를 누르면 Ride가 끝나기 때문에 운전자와 승객 모두 Home 페이지로 이동 해야 한다.

이 강의를 진행하는데, 니콜라스랑 조금 다른게 있었다. 왠지 모르겠지만, Subscription의 updateQuery가 운전자 일때는 호출되지 않았다. 그래서 RideUpdate쪽에 onCompleted에 넣었다.

  • src/routes/Ride/RideContainer.tsx

    ...
              <RideQuery query={GET_RIDE} variables={{ rideId: parseInt(rideId, 10) }}>
                {({ data: rideData, loading, subscribeToMore }) => {
                  const subscribeOptions: SubscribeToMoreOptions = {
                    document: RIDE_SUBSCRIPTION,
                    updateQuery: (prev, { subscriptionData }) => {
                      if (!subscriptionData.data) {
                        return prev;
                      }
                      const {
                        data: {
                          RideStatusSubscription: { status }
                        }
                      } = subscriptionData;
                      if (status === "FINISHED") {
                        window.location.href = "/";
                      }
                    }
                  }
                  subscribeToMore(subscribeOptions);
                  return (
                    <RideUpdate 
                      mutation={UPDATE_RIDE_STATUS}
                      refetchQueries={[{ query: GET_RIDE , variables: { rideId: parseInt(rideId, 10) }}]}
                      onCompleted={() => this.hanleRideUpdate(rideData)}
                    >
    ...
    
      public hanleRideUpdate(rideData) {
        const { 
          GetRide
        } = rideData;
        if (GetRide && GetRide.ride.status === "ONROUTE") {
          window.location.href = "/";
        }
      }
    }
    
    export default RideContainer;
    

    이렇게 하면 자동적으로 운전자와 승객쪽 모두 FINISH가 되면 Home으로 이동한다.

#2.77 Chat Screen Query

마지막 기능이 채팅하는 기능을 구현할 차례다. 먼저 Chat 페이지를 간단히 만들고, Ride 페이지에서 Chat 페이지로 이동할 수 있는 버튼을 추가 하자. routes에 Chat 디렉토리를 생성하자.

  • src/routes/Chat/ChatContainer.tsx 별 다른건 없지만 chatId가 없을 때 Home으로 이동하는 코드가 있다.

    import React from 'react';
    import { RouteComponentProps } from 'react-router-dom';
    import ChatPresenter from './ChatPresenter';
    
    interface IProps extends RouteComponentProps<any> {}
    
    class ChatContainer extends React.Component<IProps> {
      constructor(props: IProps) {
        super(props);
        if (!props.match.params.chatId) {
          props.history.push("/");
        }
      }
      public render() {
        return <ChatPresenter />;
      }
    }
    
    export default ChatContainer;
    
  • src/routes/Chat/ChatPresenter.tsx

    import Header from 'components/Header';
    import React from 'react';
    import styled from '../../typed-components';
    
    const Container = styled.div``;
    
    const ChatPresenter: React.SFC = () => (
      <Container>
        <Header title="Chat"/>
      </Container>
    );
    
    export default ChatPresenter;
    
  • src/routes/Chat/index.ts

    export { default } from './ChatContainer';
    
  • src/routes/Ride/RidePresenter.tsx Button 안에 버튼을 추가 했다.

    ...
    import { MutationFn } from "react-apollo";
    import { Link } from 'react-router-dom';
    import styled from '../../typed-components';
    
    ...
              <Buttons>
                {renderStatusButton({ user, ride, updateRideMutation })}
                {ride.status !== "REQUESTING" && (
                  <Link to={`/chat/${ride.chatId}`}>
                    <ExtendedButton value="Chat" onClick={null} />
                  </Link>
                )}
              </Buttons>
    ...
    

그리고 페이징 라우팅에 Chat 페이지를 추가하자.

  • src/components/App/AppPresenter.tsx

    ...
    import AddPlaces from "routes/AddPlace";
    import Chat from 'routes/Chat';
    import EditAccount from "routes/EditAccount";
    
    ...
    
        <Route path={"/ride/:rideId"} exact={true} component={Ride}/>
        <Route path={"/chat/:chatId"} exact={true} component={Chat}/>
        <Route path={"/edit-accoun"} exact={true} component={EditAccount}/>
      
    ...
    

    채팅 페이지로 이동하는 링크가 추가 되었다.

     2019 06 05  7 2d429ea8 7b31 45f9 85bb b20249a05135 00 20

    지금은 빈 페이지가 Chat에 보일 텐데 Chat 페이지에 ride에 대한 정보를 보여줘야 한다.

    먼저 쿼리를 만들고 쿼리를 호출하여 정보를 얻도록 하자.

    • src/routes/Chat/Chat.queries.ts 쿼리를 작성한 후 yarn codegen을 잊지 말자

      import { gql } from 'apollo-boost';
      
      export const GET_CHAT = gql`
        query getChat($chatId: Int!) {
          GetChat(chatId: $chatId) {
            ok
            error
            chat {
              passengerId
              driverId
              messages {
                id
                text
                userId
              }
            }
          }
        }
      `;
      
    • src/routes/Chat/ChatContainer.tsx

      import React from 'react';
      import { Query } from 'react-apollo';
      import { RouteComponentProps } from 'react-router-dom';
      import { USER_PROFILE } from '../../sharedQueries.queries';
      import { getChat, getChatVariables, userProfile } from '../../types/api';
      import { GET_CHAT } from './Chat.queries';
      import ChatPresenter from './ChatPresenter';
      
      interface IProps extends RouteComponentProps<any> {}
      
      class ProfileQuery extends Query<userProfile> {}
      class ChatQuery extends Query<getChat, getChatVariables> {}
      
      class ChatContainer extends React.Component<IProps> {
        constructor(props: IProps) {
          super(props);
          if (!props.match.params.chatId) {
            props.history.push("/");
          }
        }
        public render() {
          const {
            match: {
              params: { chatId } 
            }
          } = this.props;
          return (
            <ProfileQuery query={USER_PROFILE}>
              {({ data: userData }) => (
                <ChatQuery query={GET_CHAT} variables={{ chatId: parseInt(chatId, 10) }}>
                  {({ data: chatData, loading }) => ( console.log(chatData),
                    <ChatPresenter />
                  )}
                </ChatQuery>
              )}
            </ProfileQuery>
          )
        }
      }
      
      export default ChatContainer;
      

    Chat 페이지로 이동하면 간단하게 Chat 데이터를 쿼리로 날려서 콘솔로 찍히도록만 했다.

    graphql에서 chatId에 메시지를 몇개 넣자. 운전자랑 승객의 토큰으로 각각 메시지 날리자.

     2019 06 06  6 c9467783 4361 44ab 97ec f19d090be4cc 11 07

    `