References: Creating your first app
이번엔 User Account를 추가해 봅니다.
1. 유저 기능 추가하기
미티어 프레임 워크에서 제공해주는 accounts-ui와 accounts-password 패키지를 사용합니다.
콘솔에서 다음 명령을 실행합니다: meteor add accounts-ui accoutns-password
accounts-ui는 블레이즈 UI 컴포넌트이므로 리액트에서 사용하기 위해 래핑해줍니다.
/imports/ui/AccountsUIWrapper.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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() { // Use Meteor Blaze to render login buttons this.view = Blaze.render(Template.loginButtons, ReactDOM.findDOMNode(this.refs.container)); } componentWillUnmount() { // Clean up Blaze view Blaze.remove(this.view); } render() { // Just render a placeholder container that will be filled in return <span ref="container" />; } } | cs |
래퍼를 사용하도록 /imports/ui/app.jsx파일을 수정해줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import React, { Component } from 'react'; import { withTracker } from 'meteor/react-meteor-data'; import { Tasks } from '../api/tasks.js'; import ReactDOM from 'react-dom'; import Task from './Task'; import AccountsUIWrapper from './AccountsUIWrapper.jsx'; ... ... Hide Completed Tasks </label> <AccountsUIWrapper /> <form className="new-task" onSubmit={this.handleSubmit.bind(this)} > <input ... | cs |
accounts-ui의 기본 id포맷은 email입니다. 이걸 변경할 수 있도록 설정을 추가합니다.
/imports/startup/accounts-config.js
1 2 3 4 5 | import { Accounts } from 'meteor/accounts-base'; Accounts.ui.config({ passwordSignupFields: 'USERNAME_ONLY' }); | cs |
추가한 설정 파일을 적용합니다.
/clinet/main.jsx
1 2 3 4 5 6 7 8 9 10 11 | import React from 'react'; import { Meteor } from 'meteor/meteor'; import { render } from 'react-dom'; import App from '../imports/ui/App'; import '../imports/startup/accounts-config.js'; Meteor.startup(() => { render(<App />, document.getElementById('render-target')); }); | cs |
이후 화면을 확인하면 Sing in이 추가된 것을 확인할 수 있으며 이를 클릭하면 다음과 같은 화면이 출력됩니다.
2. 작업 목록에 유저 기능 적용하기.
이제 작업 목록에 유저에 대한 정보를 적용 시켜 보겠습니다.
** owner: 작업을 작성한 사용자의 _id
** username: 작업을 작성한 사용자의 이름.
/imports/ui/App.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | import React, { Component } from 'react'; import { withTracker } from 'meteor/react-meteor-data'; import { Tasks } from '../api/tasks.js'; import ReactDOM from 'react-dom'; import Task from './Task'; import AccountsUIWrapper from './AccountsUIWrapper.jsx'; import { Meteor } from 'meteor/meteor'; // App component - represents the whole app class App extends Component { constructor(props) { super(props); this.state = { hideCompleted: false, }; } handleSubmit(event) { event.preventDefault(); // Find the text field via the React ref 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 }); // Clear form ReactDOM.findDOMNode(this.refs.textInput).value = ''; } ... export default withTracker(() => { return { tasks: Tasks.find({}, { sort: { createdAt: -1 } }).fetch(), incompleteCount: Tasks.find({ checked: { $ne: true } }).count(), currentUser: Meteor.user(), }; })(App); | cs |
그리고 로그인 한 경우에만 새 작업을 생성할 수 있도록 합니다.
/imports/ui/App.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ... render() { return ( <div className="container"> <header> <h1>Todo List ({this.props.incompleteCount})</h1> <label className="hide-completed"> <input type="checkbox" readOnly checked={this.state.hideCompleted} onClick={this.toggleHideCompleted.bind(this)} /> Hide Completed Tasks </label> <AccountsUIWrapper /> { 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> ); } ... | cs |
리스트에 유저 이름과 작업이 함께 나오도록 수정합니다.
/imports/ui/Task.jsx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import React, { Component } from 'react'; import { Tasks } from '../api/tasks.js'; // Task component - represents a single todo item export default class Task extends Component { toggleChecked() { // Set the checked property to the opposite of its current value Tasks.update(this.props.task._id, { $set: { checked: !this.props.task.checked }, }); } deleteThisTask() { Tasks.remove(this.props.task._id); } render() { // Give tasks a different className when they are checked off, // so that we can style them nicely in CSS const taskClassName = this.props.task.checked ? 'checked' : ''; return ( <li className={taskClassName}> <button className="delete" onClick={this.deleteThisTask.bind(this)}> × </button> <input type="checkbox" readOnly checked={!!this.props.task.checked} onClick={this.toggleChecked.bind(this)} /> <span className="text"> <strong>{this.props.task.username}</strong>: {this.props.task.text} </span> </li> ); } } | cs |
기존에 있던 작업을 지우고 회원가입을 합니다.
이후 새로운 작업을 추가하면 다음과 같이 보입니다.
'Programming > JavaScript' 카테고리의 다른 글
NodeJS - Meteor with React Tutorial (5) (0) | 2019.02.19 |
---|---|
NodeJS - Meteor with React Tutorial (4) (0) | 2019.02.19 |
NodeJS - Meteor with React Tutorial (2) (0) | 2019.02.18 |
NodeJS - Meteor with React Tutorial (1) (0) | 2019.02.18 |
NodeJS - Meteor 프레임워크 Blaze? React? (0) | 2019.02.15 |