기본 콘텐츠로 건너뛰기

vulcanJS - 6. Posts 조회화면 만들기

지난 번 글까지 잘 따라오셨으면 사용자 하나와 Posts 하나를 얻은 상태입니다.
그럼 이제 Posts가 있으니 브라우저 화면에서 보도록 합시다.

먼저 Posts의 목록을 보여줄 Component를 만들어봅니다.
이름은 PostsListComponent가 좋겠군요.
이젠 알아서 하시죠.
$ vulcan g component
? Package name spectrum-simplebb
? Component name PostsListComponent
? Component type Class Component
? Register component Yes
하고 PostsListComponent를 만듭니다.
그리고 HomeComponent.jsx안에 PostsListComponent를 넣어 봅니다.
import React, { Component } from 'react';
import { registerComponent, Components } from 'meteor/vulcan:core';
class HomeComponent extends Component {
  render () {
    return (
      <div>
        Find me at packages/spectrum-simplebb/lib/components/HomeComponent.jsx
        <Components.PostsListComponent />
      </div>
    );
  }
}
registerComponent('HomeComponent', HomeComponent);
export default HomeComponent;
render가 반환값의 마지막 부분에 <Components.PostsListComponent /> 를 추가합니다.
앗차. import 에서도 Components 를 추가해줍니다.

<Components.PostsListComponent /> 해도 되는 걸까요? import로 PostsListComponent를 사용하지 않고?
됩니다. 사실 이제까지 만들어 온 Components들도 export를 꼭 할 필요는 없습니다.
왜냐면 registerComponent로 등록을 이미 했기 때문이죠.
registerComponent로 등록한 Components들은 Components 객체에서 참조 가능합니다.
이는 편리하기도 하지만 이미 registerComponent로 등록한 Component들은 replaceComponent 같은 것으로 교체하거나 확장할 수 있어서 매우 편리합니다.

여기까지 하면 웹브라우저는 아마도
Find me at packages/spectrum-simplebb/lib/components/HomeComponent.jsx
Find me at packages/spectrum-simplebb/lib/components/PostsListComponent.jsx
이렇게 보일 겁니다.
PostsListComponent를 구현할 시간입니다.

import Posts from "../modules/posts/collection.js"
를 먼저 import 부분에 넣어서 Posts 객체를 가져오고 
vulcan:core에서 withList도 가져오고
registerComponent에도 withList와 collection 인자를 추가합니다.
import React, { Component } from 'react';
import { registerComponent, withList } from 'meteor/vulcan:core';
import Posts from "../modules/posts/collection.js"
class PostsListComponent extends Component {
  render () {
    return (
      <div>
        Find me at packages/spectrum-simplebb/lib/components/PostsListComponent.jsx
      </div>
    );
  }
}
registerComponent('PostsListComponent', PostsListComponent, [withList, {
  collection: Posts
}]);
export default PostsListComponent;
아마도 이렇게 되겠지요.
Posts야 값을 가져오려고 import 했을테고 withList(http://docs.vulcanjs.org/data-loading.html#withList)는 뭘까요?
이전 글에서 graphiQL 도구에서 본 PostsList 처럼 List를 가져오는 High Ordered Component(이하 HoC)입니다.
HoC는 단순히 React Component에서 호출하여 추가 Props을 제공합니다.
render() 아래 return에 breakpoint를 잡고 props를 관찰해봅니다.

props에 results라는 Array가 보인다.

이 Array 값을 보면
Posts의 내용이 있다!
그럼 이걸 Component에 반영해보자.
map을 사용해 render에 그려지게 수정해보면
import React, { Component } from 'react';
import { registerComponent, withList } from 'meteor/vulcan:core';
import Posts from "../modules/posts/collection.js"
class PostsListComponent extends Component {
  render () {
    return (
      <div>
        {
          this.props.results.map(o=><div key={o._id}>{o.title}</div>)
        }
      </div>
    );
  }
}
registerComponent('PostsListComponent', PostsListComponent, [withList, {
  collection: Posts
}]);
export default PostsListComponent;
최종 소스는 이와 같다.
충돌이 안나게 _id를 key로 정해주고 title을 넣어주었다.
this.props.results가 없을 경우도 있으므로 안전하게 this.props.results && this.props.results.map ... 과 같이 써주면 더 좋겠다.

이번엔 좀 어려웠다.
Components 객체와 HoC에 대해서 대충 넘어간 면이 있는데 기회가 되면 더 자세히 다뤄보도록 하겠다.
다음엔 쓰기 기능을 구현해보자.

이 블로그의 인기 게시물

Mac 주의 - 약간 빡치는 git 대소문자 변환 파일명 변환(renaming)하는 법

Mac에서 종종 화나는 일 중 하나가 파일 시스템이 대소문자를 구분하지 않는 점이다.
가령, A.png를 a.png로 바꿔야할 경우 HFS 기준으론 전혀 바뀐 점이 없는 걸로 인식하는데 다소 화가난다.
하지만, 방법이 없는 것은 아닌데

A.png를 임의의 다른 파일로 바꾼다. (ex. A_.png)1에서 바꾼 상태에서 staging 한다. (git add A_.png)1의 파일을 다시 원래 바꾸려고 했던 파일로 바꾼다. (mv A_.png a.png)3을 다시 staging 한다. (git add a.png)commit 한다.https://stackoverflow.com/a/40307511/880991 에서 답변해준 Chris Barr 님에게 감사를.
* 추가

실제로 해보니 git mv --force A.png a.png 가 더 간단하다. 이는 바로 staging 영역에 add까지 해준다.

즐거운 Online Prototyping Tool 들

jsbin, codepen, jsfiddle 이런 것들은 일단 생략. 너무 유명한 것들이라.

https://launchpad.graphql.com - node.js 기반 graphQL 연습장. 이것만으로도 충분히 훌륭한 백엔드
https://codesandbox.io/ npm 사용이 가능한 클라이언트 사이드 연습장. webpackbin이 너무 문제가 많아서 찾아본 것.

https://scrimba.com 이건 codesandbox+ asciinema(https://asciinema.org/) 같은 느낌인데 키 녹화와 음성 녹화 기능이 추가되었다. 다 좋은데 화살표 키로 빨리감기 뒤로감기 기능이 안되고 익스포트(youtube등)으로 지원이 없는게 아쉽다.

이 둘이 만나면? https://codesandbox.io/s/jvlrl98xw3?from-embed
뭐야 이거 무서워 하지마 ㄷㄷ;  graphql+react-native-web(부왘ㅋㅋ)

https://repl.it/languages 전통을 자랑하는 REPL 도구. 지원 언어 종류가 -_-;;;;;

https://tio.run/# repl.it? 장난함? 얘는 지원 언어가 무려 386종류. J랑 아희도 있다.

https://play.golang.org/ 즐거운 go playground. 소스 포멧팅 넘 좋아.

http://decaffeinate-project.org/repl/ 최고의 coffeescript REPL. 원래 용도는 coffee를 ecma6코드로 바꾸는 것이지만...

https://scaphold.io
https://www.graph.cool/ graphql backend service. scaphold.io는 설치도 필요없는 클라우드. graphcool은 호스팅+클라우드 다있음. 둘 다 막상막하. 푸쉬서버도 되고 뭐 미친득.

https://glitch.com/ gomix에서 결국 glitch로 안착.  node.js

https://www.shadertoy.com 잘하고 싶다! 쉐이다! 오디오도 된다!

http:/…

graphql 연습 /w launchpad

https://launchpad.graphql.com/mw9wkzv99
단순 전체쿼리+조건쿼리+추가

http://graphql.org/graphql-js/passing-arguments/
참고. random ID는 crypto 1.0.1 사용
  type Query {
    Members: [member]
    getMember(id: ID!): member
  }
  type member {
    id: ID!
    text: String
  }
  input memberInput {
    text: String
  }
  type Mutation {
    addMember(member: memberInput): member
  } SQL 정의. facebook 쪽은 스트링에 지지는 거 진짜 좋아하네. *.gql 파일이 있다고 하니 이해해주자.
resolver는 var buffer = [];
const resolvers = {
  Query: {
    Members: (root, args, context) => {
      return buffer;
    },
    getMember: (id)=> {
      return buffer.find(o=>o.id)
    }
  },
  Mutation: {
    addMember(_, {member}) {
      const mm = { ...member, id:randomBytes(10).toString('hex') };
      buffer.push(mm);
      return mm;
    }
  }
}; 평범 평범.
https://dev-blog.apollodata.com/tutorial-graphql-subscriptions-server-side-e51c32dc2951 다음으로 pub/sub 연습.
https://launchpad.graphql.com/xvn94n3ql   type Subscription {
    memberAdded: member
  } member가 added되는 순간을 감시. imp…