ãµã¼ãã¼ãµã¤ãããã°ã©ãã¼ã®ããã®React.js å ¥é 3. ãããã React.js ãæ¸ã
ãããã React.js å ¥é
éçºç°å¢ä½æã«2åã使ãã¾ããããä»åãã React.js ãå§ãã¾ãã
éçºç°å¢ã¨ãããã¨ãã£ã¿ã¼ã§ããã主ãªã¨ãã£ã¿ã¼ã¯ JSX, ES6 ããµãã¼ãããæ¡å¼µããã±ã¼ã¸ããã¯ãçãããã¨æãã¾ãã®ã§å ¥ãã¦ããã¾ãããããã¡ã WebStorm ã®ãããªIDEãè¯ãããããã¾ããã
ããããä½ãTodoã¢ããªã¯Ruby on Railsã®ãµã¼ãã¼ã¨httpãããã³ã«ã§éä¿¡ããå¿ è¦ãããã¾ããããã§ä»åã¯éä¿¡é¨åã«ã¯ãPromisãã¼ã¹ã®ä»é¢¨ãªHTTP clinet ã©ã¤ãã©ãªã¼ axios ã使ã£ã¦ã¿ã¾ãã 使ãæ¹ã¯æ¥µãã¦ã·ã³ãã«ã§ãã
ã¤ã³ã¹ãã¼ã«ã¯
$ npm install --save-dev axios
ã¾ãã¯ãè¶ ç°¡åãªReact.js ã¢ããªãåãã
ååæ¸ãã index.js ã以ä¸ã®ããã«å¤æ´ãã¦ãã ããããã¡ããã¿ã¼ããã«ã§ã¯ webpack -d -w
ãå®è¡ãã¦ä¸ããã
ã¾ããå¥ã®ã¿ã¼ããã«ã§ã¯ rails s
ã§Ruby on Rails ã®ãµã¼ãã¼ãèµ·åãã¦ããã¦ä¸ããã
import React, { Component } from 'react' import ReactDOM from 'react-dom' import axios from 'axios' class IndexPage extends Component { constructor(props) { super(props) this.state = {todos: []} } componentDidMount() { axios.get('/todos.json').then((response) => { this.setState({todos: response.data}) }).catch((response) => { console.log(response) }) } render() { return ( <div> <h2>List of Todos</h2> {this.state.todos.map((todo) => <div>{todo.task}</div>)} </div> ) } } ReactDOM.render( <IndexPage />, document.getElementById('example') )
React.js 㯠ç»é¢ãã³ã³ãã¼ãã³ã(é¨å)ã«åå²ãããã®ã³ã³ãã¼ãã³ãã¯ç¬èªã®HTMLã¿ã°ã«ãªãã¾ãã
ä¸ã§ã¯ <IndexPage>
ã¨ããã³ã³ãã¼ãã³ããå®ç¾©ããããä¸çªä¸ã® ReactDOM.render() 㧠index.html ã«ãã <div id='example'></div>
ã®ä¸ã«åãè¾¼ããã¨ã§ã³ã³ãã¼ãã³ãã表示ããã¾ãã
ãã©ã¦ã¶ã¼ã®Consoleã« warnig ã表示ããã¦ãã¾ããå 容ã«ã¤ãã¦ã¯å¾ã§èª¬æãã¾ããããã®ããã« React ã¯ä½ãããããã¨ããããã㨠warnig ã表示ãã¦ããã¾ããããã¯éçºã»ãããã¯ã®å©ãã«ãªãã®ã§ã¡ããã¨å¯¾å¿ãã¦ä¸ããã
解説
state
Reactã®ã³ã³ãã¼ãã³ã㯠Component ã¯ã©ã¹ãç¶æ¿ãã¦ä½ãã¾ããã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ã¼(constructor) ã®ä¸ã§ ããããã£ã¼(ã¤ã³ã¹ã¿ã³ã¹å¤æ°)ãå®ç¾©ãã¦ãã¾ãã
state ã¯éè¦ãªããããã£ã¼ã§ããã®ã³ã³ãã¼ãã³ããä¿æããç¶æ ããã¼ã¿ãªã©ãä¿æãããªãã¸ã§ã¯ã(Hashã¨ãã¦ä½¿ã£ã¦ã¾ã)ããã㧠todos 㯠ãµã¼ãã¼ããåå¾ããTodoæ å ±ã®é åã§ããé©åãª(å¾ã§èª¬æãã¾ã)åæå¤ãæ¸ãã¦ããã¦ä¸ããã
render
次㫠render() ã¡ã½ãããè¦ã¦ã¿ã¾ããããããã¯ç»é¢ã«è¡¨ç¤ºãããHTMLãæ»ãã¡ã½ããã§ãã JS(JavaScript)ã®ä¸ã«HTML ã¿ã°ãæ¸ããã¦ãã¾ããããããJSXã§ç°å¢è¨å®ã§å ¥ããBabelããã®é¨åãé常ã®JSã«å¤æãã¦ããã¾ãããã®HTMLã¿ã°ã®é¨å㯠JSã®å¼ã¨ãã¦æ±ããã¾ãã
JSXã®ä¸ã® { ããã } ã«ã¯JSã®å¼ãæ¸ããã¾ãããã®å¤ãã¿ã°ãå±æ§å¤ã¨ãã¦ä½¿ããã¾ãã<div>{todo.task}</div>
ã® todo.task ã¯ã¿ã¹ã¯ã®æååã«ãªãã¾ãã
this.state.todos.map
ã®é¨å㯠state å
ã® todos ã®å¤(é
å)ããtaskæååã表示ããHTMLã®åãçæãã¦ãã¾ãã ES6ã使ã£ã¦ã³ã³ãã¯ãã«æ¸ãã¦ã¾ãããES5 ã§æ¸ãã¨
{this.state.todos.map(function(todo) { return <div>{todo.task}</div> })}
ãµã¼ãã¼ãµã¤ãã®viewã¨ä¼¼ãæãã§ããããµã¼ãã¼ãµã¤ãã®viewã1ãã¼ã¸å ¨ä½(ã¾ãã¯ãã¼ã¸å ã®ä¸é¨å)ããªã¯ã¨ã¹ãæ¯ã«ä¸åº¦ã«ä½æããããã« Reactãå¿ è¦ãªã¿ã¤ãã³ã°ã§ä¸åº¦ã«ãã¼ã¸å ¨ä½ãä½æããããã«ããã°ã©ãã³ã°ãã¾ãã
jQueryãªã©ã使ã£ãAjaxã§ã¯ããã°ã©ãã¼ãå¤æ´ãã¹ãé¨åã®ã¿ãæ¸ãæããããã«ããã°ã©ãã³ã°ããå¿ è¦ãããã¾ããããªããªãHTMLå ¨ä½ãæ¸ãæããã®ã§ã¯é ã使ããããUIãå®ç¾ã§ããªãããã§ãããã®ä»£åã¨ãã¦ã³ã¼ããç ©éã«ãªããã¡ã³ããã³ã¹ãã¥ããã³ã¼ãã«ãªããã¡ã§ããã
React㯠HTMLå ¨ä½ãæ¸ãæãããããªããã°ã©ãã³ããã¦ãã©ã¤ãã©ãªã¼ãç¾å¨ã®DOM(HTMLæ§é )ã¨æ°ããDOM(HTMLæ§é )ãæ¯è¼ããå¿ è¦ãªé¨åã®ã¿ãæ¸ãæãã¦ããã¾ãã
ãã® Virtual DOM ã¨ããä»æãããç»é¢å ¨ä½ãæ¸ãæããã¨ããã·ã³ãã«ãªããã°ã©ãã³ã¢ãã«ã¨æ§è½ã両ç«ãã¦ããã¾ãã
ReactãçæããHTML(ä¸ã®ç»å)ãè¦ãã¨ãdata-reactid ã¨ããå±æ§ãåã¿ã°ã«ãµããã¦ãã¾ããããã¯Virtual DOMã¨å®éã®DOMã®ç®¡çã«ä½¿ããã¦ããã®ã ã¨æããã¾ãã
componentDidMount (ã³ã³ãã¼ãã³ãã®ã©ã¤ããµã¤ã¯ã«)
Reactã§ã¯ã³ã³ãã¼ãã³ãã®è¡¨ç¤ºãæ示çãªå¶å¾¡ã¯ãã Reactã©ã¤ãã©ãªã¼ã«ä»»ãã¾ããã·ã³ãã«ãªã³ã³ãã¼ãã³ã㯠render ã¡ã½ããã ãã§ãåºæ¥ã¾ãããé常ã¯ãã¼ã¿ãåå¾ããããããããªå¦çãå¿ è¦ã«ãªãã¾ããããã§Reactã§ã¯è¡¨ç¤ºå¦çã®ããã¿ã¤ãã³ã°ã§å¼ã³åºãããã¡ã½ããã決ã¾ã£ã¦ãã¾ãããããèªåã§ãªã¼ãã¼ã©ã¤ããå¦çãçµã¿è¾¼ã¿ã¾ãã 詳細ã¯Component Specs and Lifecycle ãè¦ã¦ä¸ãããåã£ãUIãä½ã£ãããReact以å¤ã®JSã©ã¤ãã©ãªã¼ã¨çµã¿ããå ´åãªã©ã¯ãã®ã©ã¤ããµã¤ã¯ã«ãçç¥ããå¿ è¦ãããã¾ãã
ç¾å¨ãReactã使ãã¢ããªãä½ã£ã¦ãã¾ãããåã£ãäºã¯ãã¦ãªãã®ã§ãã»ã¨ãã©ã³ã³ãã¼ãã³ãã¯
- componentDidMount() æåã«ã³ã³ãã¼ãã³ããæç»ãããå¾ã«å¼ã³åºããã
- componentWillReceiveProps(nextProps) ã³ã³ãã¼ãã³ããåæç»ãããéã«å¼ã³åºããã(æ£ç¢ºã«ã¯æ°ããªpropsãåãåãæãpropsã¯å¾ã§èª¬æãã¾ã)
ã®2ã¤ã§æ¸ãã§ã¾ãã Component Specs and Lifecycle ã«æ¸ããã¦ããããã« ãã¼ã¿ã®åå¾çã¯componentDidMountã¡ã½ããã«å®è£ ãã¾ãã
componentDidMountã¯æåã®æç»ã®å¾ã«å¼ã³åºããã¾ããä»åã®ã³ã¼ãã§ã¯todosã®åæå¤ã¯ç©ºé
åãªã®ã§ãæå㯠<div><h2>List of Todos</h2></div>
ã表示ããã¾ã(ãã¡ããè¦ãã¾ããã)ã
ãã®å¾ componentDidMount ãå®è¡ãã Railsãµã¼ãã¼ããTodoæ
å ±ãåå¾ãã¦ãã¾ãã axios ã®è©³ç´°ã¯ axiosã®GitHub ã«æ¸ããã¦ãã¾ãããè¦ãªãã¨ãæ³åã§ããã¨æãã¾ãã
- get() ã§GETãªã¯ã¨ã¹ãããµã¼ãã¼ã«éã
- ãã¼ã¿ãåå¾ã§ãã㨠then() ã«æ¸ããã(ç¡å)é¢æ°ãå®è¡ããã¾ã
- ã¨ã©ã¼ãèµ·ããå ´å㯠catch() ã«æ¸ããã(ç¡å)é¢æ°ãå®è¡ããã¾ã
ãã¼ã¿ãåå¾ã§ããã this.setState()
ã¡ã½ãããå¼ã³åºããã¦ãã¾ãã Reactã§ã¯stateã®æ´æ°ã¯ããããã£ã¼ã¸ã®ä»£å
¥ã§ã¯ãªãããã®ã¡ã½ãããå¼ã³åºãå¿
è¦ãããã¾ãã
this.setState()
ã¯å¤æ´ããã state ã使ãåæç»ãè¡ãã¾ãã(ä¸ã®renderã§èª¬æããããã« Virtual DOM ã«ããå®éã«æãããã®ã¯todo.task表示ã®divã¿ã°ã®ã¿ã§ã)
注æç¹
ç§ããåã㦠Reactã使ã£ã¦ããã£ãç¹ãªã©ãæ¸ãã¦ããã¾ãã
- ä¸åº¦è¡¨ç¤ºãããã³ã³ãã¼ãã³ãã¯ã¤ã³ã¹ã¿ã³ã¹ãã¡ã¢ãªä¸ã«æ®ã£ã¦ããã®ã§ãä»ã®ã³ã³ãã¼ãã³ãããå表示ãèµ·ããã¦ã componentDidMount ã¯å®è¡ããã¾ããããã®æ㯠componentWillReceiveProps ãå¼ã³åºããã¾ã
- ä¸ã«ãæ¸ãã¾ããããæåã¯ãã¼ã¿ã空(åæå¤)ã®ç¶æ ã§æç»ãèµ·ããã®ã§ãåæå¤ã¯éè¦ã§ããé©åãªå¤ãè¨å®ãã¦ããããrenderã®æ¹ã§ç©ºãã¼ã¿ãèæ ®ããªãã¨null絡ã¿ã®ã¨ã©ã¼ãçºçãã¾ã
- renderã§æãããã³ã³ãã¼ãã³ãã¯åºæ¬çã«1ã¤ã®ã¿ã°ã§ããå¿ è¦ãããã¾ããä»åã®ã³ã¼ãã§ã¯HTMLçã«ã¯æåã®divã¿ã°ã¯ãããªãã®ã§ããã ãã®Reactã®å¶éãã div ã§æ¬ã£ã¦ãã¾ã
- List of Todosã®ç»é¢ã§çºçãã¦ãã Warning: Each child in an array or iterator should have a unique "key" prop. ... ã§ããããªã¹ãããã¼ãã«ã®ããã«è¦ç´ æ°ãå¯å¤ã®ã¿ã°ãæ£ããReactãèªèåºãããã«key å±æ§ã§ã¦ãã¼ã¯ãªå¤ãè¨å®ããå¿ è¦ãããã¾ããä»åã®ã³ã¼ãã¯æ£ããã¯ä»¥ä¸ã®ããã«æ¸ãã¾ã
ã»ã»ã» çç¥ ã»ã»ã» render() { return ( <div> <h2>List of Todos</h2> {this.state.todos.map((todo) => <div key={todo.id}>{todo.task}</div>)} </div> ) } } ã»ã»ã» çç¥ ã»ã»ã»
Todoãªã¹ã表示å®æç
Todoãªã¹ãã®è¡¨ç¤ºãã¼ã¸ãã
- ãã¼ã¸å ¨ä½
- Todoãªã¹ã表示
- Todoä¸é ç®è¡¨ç¤º
ã¨ããã³ã³ãã¼ãã³ãã«åå²ãã¦ã¿ã¾ããããã³ã³ãã¼ãã³ãã«ã¯HTMLã®å±æ§ã®ããã«å¤ã渡ããã¨ãã§ãã¾ãã
å¤ãåãåãã³ã³ãã¼ãã³ãå´ã§ã¯ãthis.props.å±æ§å
ã§å¤ãã¢ã¯ã»ã¹ãã¾ãã ãã® props ãéè¦ãªããããã£ã¼ã§ããã¾ããpropsã®å¤ãã³ã³ãã¼ãã³ãå
ã§å¤æ´ããªãã®ã React ã®èãæ¹ã§ãã
TodoList.propTypes = {
ããå§ã¾ãé¨åã§ãããpropã®åã宣è¨ããé¨åã§ããç¡ãã¦ãåä½ãã¾ããå宣è¨ããã¦ãã㨠éãåã渡ãããå ´å waring ãçºçããã®ã§ãéçºã«ã¯å½¹ç«ã¤ã¨æãã¾ãã
詳細㯠Prop Validation ãåç §ãã¦ä¸ãã
import React, { Component, PropTypes } from 'react' import ReactDOM from 'react-dom' import axios from 'axios' class IndexPage extends Component { constructor(props) { super(props) this.state = {todos: []} } componentDidMount() { axios.get('/todos.json').then((response) => { this.setState({todos: response.data}) }).catch((response) => { console.log(response) }) } render() { return( <div> <h2>List of Todos</h2> <TodoList todos={this.state.todos}/> </div> ) } } class TodoList extends Component { render() { return( <table> <thead> <tr> <th>Due</th> <th>Task</th> <th colSpan="3"></th> </tr> </thead> <tbody> {this.props.todos.map((todo) => (<TodoListItem key={todo.id} todo={todo} />))} </tbody> </table> ) } } TodoList.propTypes = { todos: PropTypes.array.isRequired } class TodoListItem extends Component { render() { return( <tr> <td> {this.props.todo.due} </td> <td> {this.props.todo.task} </td> </tr> ) } } TodoListItem.propTypes = { todo: PropTypes.object.isRequired } ReactDOM.render( <IndexPage />, document.getElementById('example') )
äºå
次åã¯ãTodoæ å ±ã®å¤æ´ãªã©ã«ä»ãã¦æ¸ãã¾ãã