Entrepreneurship-bootcamp-02 / std-r

Metero Simple Todos React Sample
0 stars 2 forks source link

Do it 8. user accouts 사용하기 #8

Open dkmin opened 8 years ago

dkmin commented 8 years ago

https://www.meteor.com/tutorials/react/adding-user-accounts

Do it 8 전체 진행 단계

  1. 프로젝트에 패키지 추가
  2. 로그인 창 화면에 띄우기
  3. 로그인한 사용자 정보를 Tasks 필드에 추가하기
  4. Tasks 필드 정보를 화면에 찍어보기
  5. 로그인한 사용자 정보기준 조건 추가하기

  1. 프로젝트에 2개 추가 > meteor add accounts-ui accounts-password
  2. 개발 모드 진입(발진!) > meteor

imports/ui/AccountsUIWrapper.jsx

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Template } from 'meteor/templating';
import { Blaze } from 'meteor/blaze';

export default class AccountsUIWrapper extends Component {
  componentDidMount() {
    // Meteor Blaze 에 있는 render login buttons 사용하는 방법
    this.view = Blaze.render(Template.loginButtons,
      ReactDOM.findDOMNode(this.refs.container));
  }
  componentWillUnmount() {
    // Clean up Blaze view
    Blaze.remove(this.view);
  }
  render() {
    // placeholder container 입니다=여기에 결과가 랜더링 결과가 들어옴. 
    return <span ref="container" />;
  }
}

imports/ui/App.jsx

import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { createContainer } from 'meteor/react-meteor-data';

import { Tasks } from '../api/tasks.js';

import Task from './Task.jsx';
import AccountsUIWrapper from './AccountsUIWrapper.jsx'; // Add compo def here

// App compo => 예제 앱 전체를 여기에 정의
class App extends Component {

  handleSubmit(event) {
    event.preventDefault();

    // ref="textInput" 를 찾아서 value 를 text 에 대입
    const text = ReactDOM.findDOMNode(this.refs.textInput).value.trim();

    Tasks.insert({
      text,
      createdAt: new Date(), // current time
    });

    // DB instert 후 폼에 있는 값을 ''로 지위줌
    ReactDOM.findDOMNode(this.refs.textInput).value = '';
  }

  renderTasks() {
    return this.props.tasks.map((task) => (
      <Task key={task._id} task={task} />
    ));
  }

  render() {
    return (
      <div className="container">
        <header>
          <h1>Todo List</h1>

          <AccountsUIWrapper />  {/* Add compo tag here  */}

          <form className="new-task" onSubmit={this.handleSubmit.bind(this)} >
            <input
              type="text"
              ref="textInput"
              placeholder="Type to add new tasks"
            />
          </form>

        </header>

        <ul>
          {this.renderTasks()}
        </ul>
      </div>
    );
  }
}

App.propTypes = {
  tasks: PropTypes.array.isRequired,
};

export default createContainer(() => {
  return {
      tasks: Tasks.find({}, { sort: { createdAt: -1 } }).fetch(),
  };
}, App);

imports/startup/accounts-config.js

import { Accounts } from 'meteor/accounts-base';

Accounts.ui.config({
  passwordSignupFields: 'USERNAME_ONLY',
});

client/main.jsx

import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';

import '../imports/startup/accounts-config.js';
import App from '../imports/ui/App.jsx';

Meteor.startup(() => {
  render(<App />, document.getElementById('render-target'));
});

여기까지 2단계 로그인 창 화면에 띄우기 완료

dkmin commented 8 years ago

Do it 8 전체 진행 단계

  1. 프로젝트에 패키지 추가
  2. 로그인 창 화면에 띄우기
  3. 로그인한 사용자 정보를 Tasks 필드에 추가하기
  4. Tasks 필드 정보를 화면에 찍어보기
  5. 로그인한 사용자 정보기준 조건 추가하기

imports/ui/App.jsx

import React, { Component, PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { Meteor } from 'meteor/meteor'; // Add Meteor Package <==
import { createContainer } from 'meteor/react-meteor-data';

import { Tasks } from '../api/tasks.js';

import Task from './Task.jsx';
import AccountsUIWrapper from './AccountsUIWrapper.jsx';

// App compo => 예제 앱 전체를 여기에 정의
class App extends Component {

  handleSubmit(event) {
    event.preventDefault();

    // ref="textInput" 를 찾아서 value 를 text 에 대입
    const text = ReactDOM.findDOMNode(this.refs.textInput).value.trim();

    Tasks.insert({
      text,
      createdAt: new Date(),           // current time
      owner: Meteor.userId(),          // id of logged in user <==
      username: Meteor.user().username // username of logged in user <==
    });

    // DB instert 후 폼에 있는 값을 ''로 지위줌
    ReactDOM.findDOMNode(this.refs.textInput).value = '';
  }

  renderTasks() {
    return this.props.tasks.map((task) => (
      <Task key={task._id} task={task} />
    ));
  }

  render() {
    return (
      <div className="container">
        <header>
          <h1>Todo List</h1>

          <AccountsUIWrapper />  {/* 로그인 compo tag  */}

            { this.props.currentUser ? // 로그인 했을 때만 보이도록 제어문 추가 <==
              <form className="new-task" onSubmit={this.handleSubmit.bind(this)} >
                <input
                  type="text"
                  ref="textInput"
                  placeholder="Type to add new tasks"
                />
              </form> : ''
            }

        </header>

        <ul>
          {this.renderTasks()}
        </ul>
      </div>
    );
  }
}

App.propTypes = {
  tasks: PropTypes.array.isRequired,
  currentUser: PropTypes.object,  // 데이터 형식이 object 임을 정의 <==
};

export default createContainer(() => {
  return {
      tasks: Tasks.find({}, { sort: { createdAt: -1 } }).fetch(),
      currentUser: Meteor.user(),  // App compo 에서 사용하도록 등록 <==

  };
}, App);

imports/ui/Tasks.jsx

import React, {Component, PropTypes} from 'react';
import {Tasks} from '../api/tasks.js';

// Task compo - single todo item을 여기에 정의
export default class Task extends Component {

  toggleChecked() {
    // checked property를 반대 값으로 update 한다. !=반대
    Tasks.update(this.props.task._id, {
      $set: {
        checked: !this.props.task.checked
      }
    });
  }

  deleteThisTask() {
    Tasks.remove(this.props.task._id);
  }

  render() {
    // CSS class 는 React에서 className 으로 사용한다.
    // 그래서 CSS style 을 쉽게 변경할 수 있다. 목적) className='checked'
    const taskClassName = this.props.task.checked
      ? 'checked'
      : '';

    return (
      <li className={taskClassName}>
        <button className="delete" onClick={this.deleteThisTask.bind(this)}>
          &times;
        </button>

        <input type="checkbox" readOnly checked={this.props.task.checked} onClick={this.toggleChecked.bind(this)}/>

        {/* 아래 3줄추가 = text 앞에 username을 보여준다 */}
        <span className="text">
          <strong>{this.props.task.username}</strong>: {this.props.task.text}
        </span>
      </li>
    );
  }
}

Task.propTypes = {
  // Task compo 는 App 에서 상속 받은 task 를 사용한다.
  // propTypes 는 Data type(자료형)을 정의하는 용도로 사용한다.
  task: PropTypes.object.isRequired
};