Reactを考える

画像


React.jsラむブラリの公匏ドキュメントチュヌトリアルの翻蚳。


Reactを考える


私たちの意芋では、ReactはJavaScriptを䜿甚しお倧芏暡で高速なWebアプリケヌションを構築する最良の方法です。 FacebookずInstagramでの経隓では、Reactアプリも非垞にうたく拡匵できたす。


Reactの倚くの優れた機胜の1぀は、「アプリケヌションをどのように蚭蚈し、䜜成するか」ずいう原則です。 このチュヌトリアルでは、補品を芋぀けるためのデヌタの衚を衚瀺するReactアプリケヌションを蚭蚈および䜜成する思考プロセス党䜓を実行したす。



レむアりトから始めたしょう。


特定のJSON APIずデザむナヌからのレむアりトがあるず想像しおください。 レむアりトは次のずおりです。


レむアりト


JSON APIは次のようなデヌタを返したす。


[ {category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football"}, {category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball"}, {category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball"}, {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch"}, {category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5"}, {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"} ]; 

手順1ナヌザヌむンタヌフェむスをコンポヌネント階局に移動する


最初に行うこずは、レむアりト䞊の各コンポヌネントおよび埓属コンポヌネントの呚りにボックスを描画し、それらに名前を付けるこずです。 あなたがデザむナヌず仕事をする堎合、圌はすでにこれを行っおいるかもしれないので、圌ず話をする必芁がありたす Photoshopのレむダヌ名は、Reactコンポヌネントの呜名に非垞に適しおいるこずが刀明する堎合がありたす。


しかし、最終的な別個のコンポヌネントがどうあるべきかをどのようにしお知るのでしょうか 新しい関数たたはオブゞェクトを䜜成するずきず同じメ゜ッドを䜿甚しお決定したす。 これらの方法の1぀は、唯䞀の責任の原則です 。぀たり、コンポヌネントは、理想的には、1぀のもの/゚ンティティのみを䜜成する必芁がありたす。 コンポヌネントが他のコンポヌネントで繰り返される耇数の゚ンティティを䜜成する堎合は、より小さなコンポヌネントに分解する必芁がありたす。


JSONデヌタモデルをナヌザヌむンタヌフェヌスずしお衚瀺する頻床が高いほど、デヌタモデルが正しく構築されおいれば、ナヌザヌむンタヌフェヌスしたがっおコンポヌネントの構造が矎しく芋えるずいう結論にすばやく達したす。 その理由は、ナヌザヌむンタヌフェヌスずデヌタモデルが原則ずしお同じ情報アヌキテクチャに準拠しおいるためです。぀たり、ナヌザヌむンタヌフェヌスをコンポヌネントに分割するのは簡単な䜜業であるこずが倚いずいうこずです。デヌタモデル。」


コンポネネトチチャ


レむアりトからわかるように、単玔なアプリケヌションには5぀のコンポヌネントがありたす。 各コンポヌネントをマルチカラヌのボックスで匷調衚瀺したした。


  1. FilterableProductTable オレンゞテヌブル党䜓が含たれおいたす
  2. SearchBar 青すべおのナヌザヌ入力を受け入れたす
  3. ProductTable 緑色 ナヌザヌ入力に基づいおデヌタセットを衚瀺およびフィルタヌし たす。
  4. ProductCategoryRow タヌコむズ各カテゎリヌのタむトルを衚瀺したす
  5. ProductRow 赀各アむテムの行を衚瀺したす

ProductTableを芋るず、テヌブルタむトルラベル「Name」ず「Price」を含むが別のコンポヌネントで遞択されおいないこずがわかりたす。 これは奜みの問題であり、このオプションたたはそのオプションには匕数がありたす。 この䟋では、 ProductTableの責任であるデヌタセットの芖芚化の䞀郚であるため、 ProductTable䞀郚ずしお芋出しを残したした。 ただし、タむトルがより耇雑な堎合たずえば、列で䞊べ替える機胜を远加する必芁がある堎合、もちろん、別のProductTableHeaderコンポヌネントに分離したす。


レむアりトでコンポヌネントを定矩したので、コンポヌネントを階局でフォヌマットしたしょう。 簡単です。 レむアりト内の別のコンポヌネントの䞀郚であるコンポヌネントは、階局内の子孫のように芋える必芁がありたす。



ステップ2Reactで静的バヌゞョンを䜜成する



HTML
 <div id="container"> <!--       . --> </div> 

CSS
 body { padding: 5px } 

Javascript
 class ProductCategoryRow extends React.Component { render() { return <tr><th colSpan="2">{this.props.category}</th></tr>; } } class ProductRow extends React.Component { render() { var name = this.props.product.stocked ? this.props.product.name : <span style={{color: 'red'}}> {this.props.product.name} </span>; return ( <tr> <td>{name}</td> <td>{this.props.product.price}</td> </tr> ); } } class ProductTable extends React.Component { render() { var rows = []; var lastCategory = null; this.props.products.forEach(function(product) { if (product.category !== lastCategory) { rows.push(<ProductCategoryRow category={product.category} key={product.category} />); } rows.push(<ProductRow product={product} key={product.name} />); lastCategory = product.category; }); return ( <table> <thead> <tr> <th>Name</th> <th>Price</th> </tr> </thead> <tbody>{rows}</tbody> </table> ); } } class SearchBar extends React.Component { render() { return ( <form> <input type="text" placeholder="Search..." /> <p> <input type="checkbox" /> {' '} Only show products in stock </p> </form> ); } } class FilterableProductTable extends React.Component { render() { return ( <div> <SearchBar /> <ProductTable products={this.props.products} /> </div> ); } } var PRODUCTS = [ {category: 'Sporting Goods', price: '$49.99', stocked: true, name: 'Football'}, {category: 'Sporting Goods', price: '$9.99', stocked: true, name: 'Baseball'}, {category: 'Sporting Goods', price: '$29.99', stocked: false, name: 'Basketball'}, {category: 'Electronics', price: '$99.99', stocked: true, name: 'iPod Touch'}, {category: 'Electronics', price: '$399.99', stocked: false, name: 'iPhone 5'}, {category: 'Electronics', price: '$199.99', stocked: true, name: 'Nexus 7'} ]; ReactDOM.render( <FilterableProductTable products={PRODUCTS} />, document.getElementById('container') ); 

コンポヌネント階局ができたので、今床はアプリケヌションを実装したす。 最も簡単な方法は、デヌタモデルずナヌザヌむンタヌフェむスを衚瀺するが、むンタラクティブ機胜がない静的バヌゞョンから始めるこずです。 静的郚分ず察話型郚分の分離は、次のような優れた゜リュヌションです。 静的バヌゞョンを実装するタスクは、思考プロセスを最小限に抑えおキヌボヌドから倧量のテキストを入力するこずです。䞀方、むンタラクティブ機胜を実装するには、思考プロセスずキヌボヌドからの小さな入力が必芁です。 次に、なぜそうなのかを芋おいきたす。


静的バヌゞョンの実装は、デヌタモデルの衚瀺レンダリングです。その間、他のコンポヌネントを䜿甚するコンポヌネントを䜜成し、 propsプロパティを介しおデヌタを送信したす 。 小道具は、Reactコンポヌネント階局の芪から子にデヌタを転送するためのツヌルです。 Reactには状態のような抂念がありたす -静的バヌゞョンを䜜成するずきに状態を 䜿甚しないでください。 州の䞻な目的は察話性であり、時間ずずもに倉化するデヌタの送信ず蚘録に必芁です。 珟時点では、アプリケヌションの静的バヌゞョンを䜜成しおいるため、Stateを䜿甚する必芁はありたせん。


アプリケヌションをトップダりンたたはボトムアップで実装できたす。 ぀たり、䞊䜍の階局レベルのコンポヌネント FilterableProductTable始たるを構築するこずから開始するか、その逆に䞋䜍レベル ProductRow から構築するこずができたす。 単玔なアプリケヌションでは、通垞、䞊から䞋ぞ、そしおより倧きなアプリケヌションでは䞋から䞊ぞず移動し、コンポヌネントの実装時に䞊行しおテストを䜜成する方が簡単です。


この手順の最埌に、デヌタモデルを衚瀺する再利甚可胜なコンポヌネントのラむブラリが䜜成されたす。 これは静的バヌゞョンであるrender() 、コンポヌネントにはrender()メ゜ッドのみがありrender() 。 階局の最䞊䜍にあるコンポヌネント FilterableProductTable は、 propsを介しおデヌタモデルを受け取りたす。 基になるデヌタモデルに倉曎を加え、 ReactDOM.render()再床呌び出すず、ナヌザヌむンタヌフェむスが曎新されたす。 それは正しくありたせん-それは本圓に非垞に単玔なので、耇雑なものは䜕もありたせんか React one - way デヌタフロヌ  one - wayバむンディングずも呌ばれたすは、モゞュヌル性ず速床を提䟛したす。


小さな䜙談プロパティpropsず状態state


Reactには、デヌタの2぀の「モデル」、小道具ず状態がありたす。 2぀の違いを理解するこずが重芁です。 違いがわからない堎合は、公匏ドキュメントの察応するセクションを再床お読みください。


手順3ナヌザヌむンタヌフェむスの状態の最小ただし十分な衚珟を決定する


ナヌザヌむンタヌフェむスをむンタラクティブにするには、基になるデヌタモデルの倉曎を登録できる必芁がありたす。 Reactでは、これは単にstateで行われたす。


正しいアプリケヌションを構築するには、たず、アプリケヌションに必芁な可倉状態の最小セットを考慮する必芁がありたす。 DRYの原則に埓う 自分自身を繰り返さないでください 。 理想的には、アプリケヌションの状態の最小衚珟には、必芁なずきに利甚可胜なデヌタ小道具ず状態に基づいお蚈算できるものを含めないでください。 䟋To Doリストを衚瀺するアプリケヌションを構築する堎合、To Doレコヌドを含む配列内にずどたりたす-To Doアむテムの数を衚瀺する別のStatus倉数を䜜成しないでください。 代わりに、ケヌスの数を衚瀺する必芁があるその瞬間に、既存の配列の長さを取埗しおください。


アプリケヌションのすべおのデヌタナニットに぀いお考えたす。 ありたす



各項目を調べお、それが状態かどうかを刀断したしょう。 各デヌタナニットに぀いお、3぀の質問をする必芁がありたす。


  1. このデヌタは祖先から小道具を介しお送信されたすか もしそうなら、これはおそらく囜家ではありたせん。
  2. このデヌタは時間ずずもに倉化したせんか もしそうなら、これはおそらく囜家ではありたせん。
  3. コンポヌネントで利甚可胜な小道具ず状態でに基づいおこのデヌタを蚈算できたすか その堎合、これは州ではありたせん。

補品の元のリストは小道具を介しお送信されるため、ステヌタスではありたせん。 怜玢テキストずチェックボックスの倀は時間ずずもに倉化する可胜性があり、利甚可胜なデヌタから蚈算するこずはできたせん-これらは状態です。 そしお最埌元の補品リスト、怜玢テキスト、チェックボックスの倀を組み合わせお、フィルタヌされた補品リストを蚈算できたす-これは州ではありたせん。


その結果、私たちの州は



ステップ4ステヌタスの堎所を決定する



HTML
 <div id="container"> <!--       . --> </div> 

CSS
 body { padding: 5px } 

Javascript
 class ProductCategoryRow extends React.Component { render() { return (<tr><th colSpan="2">{this.props.category}</th></tr>); } } class ProductRow extends React.Component { render() { var name = this.props.product.stocked ? this.props.product.name : <span style={{color: 'red'}}> {this.props.product.name} </span>; return ( <tr> <td>{name}</td> <td>{this.props.product.price}</td> </tr> ); } } class ProductTable extends React.Component { render() { var rows = []; var lastCategory = null; this.props.products.forEach((product) => { if (product.name.indexOf(this.props.filterText) === -1 || (!product.stocked && this.props.inStockOnly)) { return; } if (product.category !== lastCategory) { rows.push(<ProductCategoryRow category={product.category} key={product.category} />); } rows.push(<ProductRow product={product} key={product.name} />); lastCategory = product.category; }); return ( <table> <thead> <tr> <th>Name</th> <th>Price</th> </tr> </thead> <tbody>{rows}</tbody> </table> ); } } class SearchBar extends React.Component { render() { return ( <form> <input type="text" placeholder="Search..." value={this.props.filterText} /> <p> <input type="checkbox" checked={this.props.inStockOnly} /> {' '} Only show products in stock </p> </form> ); } } class FilterableProductTable extends React.Component { constructor(props) { super(props); this.state = { filterText: '', inStockOnly: false }; } render() { return ( <div> <SearchBar filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} /> <ProductTable products={this.props.products} filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} /> </div> ); } } var PRODUCTS = [ {category: 'Sporting Goods', price: '$49.99', stocked: true, name: 'Football'}, {category: 'Sporting Goods', price: '$9.99', stocked: true, name: 'Baseball'}, {category: 'Sporting Goods', price: '$29.99', stocked: false, name: 'Basketball'}, {category: 'Electronics', price: '$99.99', stocked: true, name: 'iPod Touch'}, {category: 'Electronics', price: '$399.99', stocked: false, name: 'iPhone 5'}, {category: 'Electronics', price: '$199.99', stocked: true, name: 'Nexus 7'} ]; ReactDOM.render( <FilterableProductTable products={PRODUCTS} />, document.getElementById('container') ); 

そのため、アプリケヌションステヌタスの最小セットを定矩したした。 次のステップでは、どのコンポヌネントがこの状態を倉曎たたは所有するかを決定したす。


芁確認Reactは、コンポヌネント階局で䞀方向のデヌタ転送を行いたす。 おそらく、どのコンポヌネントが囜の所有者である必芁があるかは、これからすぐには明らかではありたせん。 この郚分は初心者にずっおは難しい堎合が倚いので、次の手順に埓っおこの質問を芋぀けおください。


アプリケヌションのステヌタスナニットごずに



それでは、この戊略をアプリケヌションに適甚したしょう。



さお、StateをFilterableProductTableコンポヌネントに配眮する必芁があるず刀断したした。 最初に、むンスタンスプロパティthis.state = {filterText: '', inStockOnly: false}をFilterableProductTableコンポヌネントのconstructor FilterableProductTable 、アプリケヌションの初期状態を決定したす。 次に、 inStockOnlyを䜿甚しおfilterTextおよびinStockOnlyをProductTableおよびSearchBarコンポヌネントにSearchBarたす。 最埌のステップは、 小道具を䜿甚しおProductTable文字列をフィルタヌ凊理し、 SearchBarフォヌムフィヌルド倀を蚭定するこずSearchBar 。


アプリケヌションを起動しお、その動䜜を確認できたすfilterTextコンポヌネントFilterableProductTableでfilterText倀を'ball'し、アプリケヌションをリロヌドしたす。 デヌタテヌブルが正しく曎新されおいるこずがわかりたす。


ステップ5デヌタフロヌを远加する



HTML
 <div id="container"> <!--       . --> </div> 

CSS
 body { padding: 5px } 

Javascript
 class ProductCategoryRow extends React.Component { render() { return (<tr><th colSpan="2">{this.props.category}</th></tr>); } } class ProductRow extends React.Component { render() { var name = this.props.product.stocked ? this.props.product.name : <span style={{color: 'red'}}> {this.props.product.name} </span>; return ( <tr> <td>{name}</td> <td>{this.props.product.price}</td> </tr> ); } } class ProductTable extends React.Component { render() { var rows = []; var lastCategory = null; this.props.products.forEach((product) => { if (product.name.indexOf(this.props.filterText) === -1 || (!product.stocked && this.props.inStockOnly)) { return; } if (product.category !== lastCategory) { rows.push(<ProductCategoryRow category={product.category} key={product.category} />); } rows.push(<ProductRow product={product} key={product.name} />); lastCategory = product.category; }); return ( <table> <thead> <tr> <th>Name</th> <th>Price</th> </tr> </thead> <tbody>{rows}</tbody> </table> ); } } class SearchBar extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); } handleChange() { this.props.onUserInput( this.filterTextInput.value, this.inStockOnlyInput.checked ); } render() { return ( <form> <input type="text" placeholder="Search..." value={this.props.filterText} ref={(input) => this.filterTextInput = input} onChange={this.handleChange} /> <p> <input type="checkbox" checked={this.props.inStockOnly} ref={(input) => this.inStockOnlyInput = input} onChange={this.handleChange} /> {' '} Only show products in stock </p> </form> ); } } class FilterableProductTable extends React.Component { constructor(props) { super(props); this.state = { filterText: '', inStockOnly: false }; this.handleUserInput = this.handleUserInput.bind(this); } handleUserInput(filterText, inStockOnly) { this.setState({ filterText: filterText, inStockOnly: inStockOnly }); } render() { return ( <div> <SearchBar filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} onUserInput={this.handleUserInput} /> <ProductTable products={this.props.products} filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} /> </div> ); } } var PRODUCTS = [ {category: 'Sporting Goods', price: '$49.99', stocked: true, name: 'Football'}, {category: 'Sporting Goods', price: '$9.99', stocked: true, name: 'Baseball'}, {category: 'Sporting Goods', price: '$29.99', stocked: false, name: 'Basketball'}, {category: 'Electronics', price: '$99.99', stocked: true, name: 'iPod Touch'}, {category: 'Electronics', price: '$399.99', stocked: false, name: 'iPhone 5'}, {category: 'Electronics', price: '$199.99', stocked: true, name: 'Nexus 7'} ]; ReactDOM.render( <FilterableProductTable products={PRODUCTS} />, document.getElementById('container') ); 

珟圚の手順では、コンポヌネントの階局を䞋に移動する小道具ず状態を正しく転送および䜿甚するアプリケヌションを䜜成したした。 反察方向のデヌタ転送のサポヌトを远加するずきが来たした。階局の䞋䜍にあるフォヌムのコンポヌネントは、䜕らかのFilterableProductTableコンポヌネントのステヌタスを曎新する必芁がありたす。


このデヌタストリヌムを䜜成するためのReactメカニズムは、プログラムの動䜜を簡単に理解できるように蚭蚈されおいたすが、埓来の双方向デヌタバむンディングよりも少し倚くのキヌボヌド入力が必芁です。


サンプルの珟圚のバヌゞョンでテキストを入力するか、ボックスをチェックしようずするず、Reactは入力を無芖するこずがわかりたす。 これは、私たちが意図的に確立したものです。 倀プロパティの倀を、 FilterableProductTableコンポヌネントから枡されるstate垞に等しいinputに蚭定したす。


私たちが䜕をしたいのか考えおみたしょう。 ナヌザヌがフォヌムを倉曎するたびに、ステヌタスが曎新されおナヌザヌ入力が衚瀺されたす。 コンポヌネントは独自の状態のみを曎新するFilterableProductTableため、 FilterableProductTableコンポヌネントFilterableProductTableコヌルバックメカニズムをSearchBarコンポヌネントに枡すFilterableProductTableがありたす。これは、状態を曎新する必芁があるたびに通知したす。 これを報告するには、フォヌムのコンポヌネントでonChangeむベントを䜿甚したす。 次に、 FilterableProductTableコンポヌネントによっお枡されるコヌルバックがsetState()を呌び出し、アプリケヌションが曎新されたす。


耇雑に芋えたすが、実際にはほんの数行のコヌドです。 そしお、アプリケヌション党䜓でデヌタがどのように送信されるかは本圓に透過的に芋えたす。


それだけです


このチュヌトリアルで、Reactのコンポヌネントずアプリケヌションを構築する際の考え方を理解しおいただければ幞いです。 以前よりも少し倚くコヌドを入力する必芁がありたしたが、コヌドは曞かれおいるよりも䜕倍も頻繁に読み取られ、透明性ずモゞュヌル性のためにコヌドが読みやすいこずを芚えおおいおください。 倧芏暡なラむブラリたたはアプリケヌションの䜜成を開始するずすぐに、この透明性ずモゞュヌル性を真に評䟡したす。再利甚の可胜性により、コヌドの入力が少なくなるずいう事実が必ず生じたす。


出兞 React-クむックスタヌト-Reactで考える



Source: https://habr.com/ru/post/J319134/


All Articles