React Native
...
Data objects
React NativeでGraphQLを使用したCRUD操作の実装ガイド
13 分
react native graphql crud チュートリアル はじめに graphqlを使用してback4appでデータを管理することは、あらゆるタイプのアプリケーションにとって強力なオプションであり、クエリを高速化し、最も複雑なものを簡素化します。back4appはgraphqlの設定に一般的な慣習を使用し、開発環境のセットアップを支援するための優れたツールを提供します。 このガイドでは、crudの例アプリを通じて基本的なデータ操作を実行する方法を学びます。このアプリは、graphqlとrelayを使用してreact nativeでparseサーバーデータベースからデータを作成、読み取り、更新、削除する方法を示します。 最初に、各crud操作のためのコンポーネント関数を作成し、後で完全な画面レイアウトで使用し、to doリストアプリを作成します。 いつでも、スタイルや完全なコードを確認するために、githubリポジトリを通じてこのプロジェクトにアクセスできます。 javascriptの例リポジトリ 前提条件 このチュートリアルでは、バージョン4 4のparse serverを使用します。他のバージョンを使用したい場合は、 https //www back4app com/docs/parse graphql/graphql logout mutation の対応するミューテーションコードを確認できます。 back4appに作成され接続されたreact nativeアプリ; 次のことを完了してください。 relay環境セットアップチュートリアル relayストアとrelayコネクションアップデーターの良い理解; relayモダンドキュメント デフォルトの実装としてjavascriptを使用します。 目標 parse、graphql、およびrelayを使用して、react nativeで基本的なcrudアプリケーションを構築すること。 1 todoクラスの作成 この最初のステップでは、アプリケーションが操作するクラスを定義する必要があります。 todo todo クラスは、タスクを説明するタイトル( string string )フィールドと、タスクが完了しているかどうかを示すdone( boolean boolean )フィールドを持つ必要があります。クラスがまだない場合は、私たちのガイドに従って、一般的なミューテーションを使用してデータベースにクラスを作成できます。 graphql cookbook https //www back4app com/docs/parse graphql/graphql mutation create object を参照してください。また、back4appのダッシュボードを使用して、データベースブラウザ自体またはjs、graphqlコンソールからクラスを作成することもできます。 この新しいクラスを作成した後、ダッシュボードから schema json schema json ファイルをダウンロードし、アプリケーション内の data data ディレクトリに保存することを忘れないでください。これは、relayコンパイラがクエリ、ミューテーションなどから自動的に型を生成するために必要です。 この時点で、back4appのダッシュボードには、クラスオブジェクトのcrudミューテーションが自動的に生成されます。それらを確認するには、graphqlコンソールに移動し、ドキュメントタブを開いて、 todo todo を検索してください。 2 オブジェクトのクエリとレンダリング では、back4appサーバーでリストクエリを行い、オブジェクトの接続を確立し、変更に応じてリストの内容を自動的にレンダリングおよび更新するコンポーネントを作成しましょう。 新しいファイルを作成します。名前は todolistqueryrenderer js todolistqueryrenderer js で、あなたの src src ディレクトリに以下のコードを追加します 1 import react from 'react'; 2 import { view, text } from 'react native'; 3 import { graphql, queryrenderer } from 'react relay'; 4	 5 // prerequisite properly configured relay environment 6 import environment from ' / /relay/environment'; 7	 8 // this will be created in the next steps 9 import todolist from ' /todolist'; 10	 11 const todolistqueryrenderer = () => { 12 return ( 13 // the queryrenderer acts as a wrapper to any code, providing query results to 14 // the child components and updating them as needed 15 // note that the query is using a fragment called todolist query, 16 // which will be created in the next steps 17 \<queryrenderer 18 environment={environment} 19 query={graphql` 20 query todolistqueryrendererquery { 21 todolist query 22 } 23 `} 24 variables={null} 25 render={({ error, props }) => { 26 if (error) { 27 return ( 28 \<view> 29 \<text>{error message}\</text> 30 \</view> 31 ); 32 } else if (props) { 33 return \<todolist query={props} />; 34 } 35 return ( 36 \<view> 37 \<text>loading \</text> 38 \</view> 39 ); 40 }} 41 /> 42 ); 43 } 44	 45 export default todolistqueryrenderer; 3 リストコンポーネントとオブジェクトのフラグメントを作成する では、queryrendererから取得したデータをレンダリングするリストコンポーネントを作成しましょう。このコンポーネントは、今のところ各ノードをレンダリングするマップ関数を含むシンプルなスクロールビューのみを含みます。srcディレクトリに「 todolist js todolist js という新しいファイルを作成し、次のコードを追加してください 1 import react, {usestate} from 'react'; 2 import { 3 view, 4 safeareaview, 5 image, 6 scrollview, 7 statusbar, 8 stylesheet, 9 touchableopacity, 10 } from 'react native'; 11	 12 import { 13 list, 14 text as papertext, 15 button as paperbutton, 16 textinput as papertextinput, 17 } from 'react native paper'; 18 import {createfragmentcontainer} from 'react relay'; 19	 20 const todolist = props => { 21 const \[newtodotitle, setnewtodotitle] = usestate(''); 22	 23 const {query} = props; 24 const {todos} = query; 25	 26 const rendertodos = () => { 27 if (!todos) { 28 return null; 29 } 30	 31 return todos edges map(({node todo}) => ( 32 \<list item 33 key={todo id} 34 title={todo title} 35 titlestyle={todo done ? styles todo text done styles todo text} 36 style={styles todo item} 37 right={props => ( 38 <> 39 {!todo done && ( 40 \<touchableopacity onpress={() => updatetodo(todo id, true)}> 41 \<list icon { props} icon="check" color={'#4caf50'} /> 42 \</touchableopacity> 43 )} 44	 45 \<touchableopacity onpress={() => deletetodo(todo id)}> 46 \<list icon { props} icon="close" color={'#ef5350'} /> 47 \</touchableopacity> 48 \</> 49 )} 50 /> 51 )); 52 }; 53	 54 return ( 55 <> 56 \<statusbar backgroundcolor="#208aec" /> 57 \<safeareaview style={styles container}> 58 \<view style={styles header}> 59 \<papertext style={styles header text bold}> 60 {'react native on back4app'} 61 \</papertext> 62 \<papertext style={styles header text}>{'product creation'}\</papertext> 63 \</view> 64 \<view style={styles create todo container}> 65 \</view> 66 \<scrollview style={styles todo list}>{rendertodos()}\</scrollview> 67 \</safeareaview> 68 \</> 69 ); 70 }; 71	 72 const todolistfragmentcontainer = createfragmentcontainer(todolist, { 73 query graphql` 74 fragment todolist query on query { 75 todos(first 50) @connection(key "todolist todos", filters \[]) { 76 edges { 77 node { 78 id 79 title 80 done 81 } 82 } 83 } 84 } 85 `, 86 }); ステップ2のクエリレンダラーは、次のようなデータのフラグメントを期待しています。 todolist query todolist query , そのため、ファイルの最後にリストコンポーネントにも追加しました。graphqlフラグメントは、コンポーネントがレンダリングするために必要なデータを呼び出し、返す必要があるものを指定する構造であることを忘れないでください。 4 オブジェクトの作成 back4app graphqlデータベースでデータを管理する最初のステップは、データを持つことです。新しい todo todo を作成するための関数を作成する必要があります。これは、ミューテーションを使用してリストコンポーネントで行います。 ミューテーションから始めましょう。新しいファイルを作成し、次のように名付けます。 createtodomutation js createtodomutation js を src/mutations src/mutations ディレクトリに作成し、次のコードを含めます。 1 import { commitmutation, graphql } from "react relay"; 2 import { root id, connectionhandler } from 'relay runtime'; 3	 4 const connectioncreateedgeupdater = (store, nodeid) => { 5 const parentproxy = store get(root id); 6 const todoconnection = connectionhandler getconnection(parentproxy, 'todolist todos'); 7	 8 const newtodo = store get(nodeid); 9 const edge = connectionhandler createedge(store, todoconnection, newtodo, 'todoedge'); 10 11 // no cursor provided, append the edge at the end 12 connectionhandler insertedgeafter(todoconnection, edge); 13 } 14	 15 const mutation = graphql` 16 mutation createtodomutation($input createtodoinput!) { 17 createtodo(input $input) { 18 todo { 19 id 20 title 21 done 22 } 23 } 24 } 25 `; 26	 27 function commit({ environment, input, oncompleted, onerror }) { 28 const variables = { input }; 29	 30 commitmutation(environment, { 31 mutation, 32 variables, 33 oncompleted, 34 onerror, 35 updater (store) => { 36 const todoid = store getrootfield('createtodo') getlinkedrecord('todo') getvalue('id'); 37	 38 connectioncreateedgeupdater(store, todoid) 39 } 40 }); 41 } relay modernは、ミューテーション呼び出し後にデータを更新するために使用できる多数のapiエンドポイントを提供します。この関数では、新しい todo todo を取得し、フロントエンド上の既存のリストを更新するためにいくつかの関数を使用しました。このアプローチにより、新しいリクエストにかかる時間、ユーザーのインターネット、過剰取得などに費やされる時間を節約し、新しいバックエンド呼び出しを回避します。 次に、以下の関数を todolist todolist コンポーネントに追加します。これは createtodomutation createtodomutation を呼び出し、後でボタンによって参照されます。 1 const createtodo = () => { 2 const input = { 3 fields { 4 title newtodotitle, 5 done false, 6 }, 7 }; 8	 9 createtodomutation commit({ 10 environment, 11 input input, 12 oncompleted () => { 13 alert alert('success!', 'todo created!'); 14 setnewtodotitle(''); 15 }, 16 onerror (errors) => { 17 alert alert('error!', errors); 18 }, 19 }); 20 } 5 オブジェクトの更新 オブジェクトの更新は、作成することに似ていますが、relay modernを使用してオブジェクトを更新する際には、ミューテーションの出力で新しい状態で更新したいフィールドを要求するだけで済みます。 新しいファイルを作成します。 updatetodomutation js updatetodomutation js を src/mutations src/mutations ディレクトリに作成し、以下のコードを含めます。 1 import { commitmutation, graphql } from "react relay"; 2	 3 const mutation = graphql` 4 mutation updatetodomutation($input updatetodoinput!) { 5 updatetodo(input $input) { 6 todo { 7 id 8 title 9 done 10 } 11 } 12 } 13 `; 14	 15 function commit({ environment, input, oncompleted, onerror }) { 16 const variables = { input }; 17	 18 commitmutation(environment, { 19 mutation, 20 variables, 21 oncompleted, 22 onerror, 23 }); 24 } 25	 26 export default { 27 commit, 28 }; 前のステップと同様に、次の関数を todolist todolist コンポーネントに追加します。これにより、 updatetodomutation updatetodomutation が呼び出され、後でボタンによって参照されます。 1 const updatetodo = (todoid, done) => { 2 const input = { 3 id todoid, 4 fields { 5 done, 6 } 7 } 8	 9 updatetodomutation commit({ 10 environment, 11 input input, 12 oncompleted () => { 13 alert alert('success!', 'todo updated!'); 14 }, 15 onerror (errors) => { 16 alert alert('error!', errors); 17 }, 18 }); 19 } 6 オブジェクトの削除 オブジェクトを削除する際、relay store apiを使用してリストを更新し、フロントエンドから古いオブジェクトを削除できます。アップデータコールバックを呼び出しますが、これは createtodo createtodo からの更新に似ています。ただし、接続と削除するto doのidを渡します。このようにして、フロントエンドをサーバーに忠実に更新し続けます。 新しいファイルを作成します。ファイル名は deletetodomutation js deletetodomutation js で、 src/mutations src/mutations ディレクトリに次のコードを含めます。 1 import { commitmutation, graphql } from "react relay"; 2 import { root id, connectionhandler } from 'relay runtime'; 3	 4 const connectiondeleteedgeupdater = (store, nodeid) => { 5 const parentproxy = store get(root id); 6 const connection = connectionhandler getconnection(parentproxy, 'todolist todos'); 7	 8 const newcount = connection getvalue('count'); 9 connection setvalue(newcount 1, 'count'); 10	 11 connectionhandler deletenode(connection, nodeid); 12 } 13	 14 const mutation = graphql` 15 mutation deletetodomutation($input deletetodoinput!) { 16 deletetodo(input $input) { 17 todo { 18 id 19 } 20 } 21 } 22 `; 23	 24 function commit({ environment, input, oncompleted, onerror }) { 25 const variables = { input }; 26	 27 commitmutation(environment, { 28 mutation, 29 variables, 30 oncompleted, 31 onerror, 32 updater (store) => { 33 connectiondeleteedgeupdater(store, input id) 34 } 35 }); 36 } 37	 38 export default { 39 commit, 40 }; 前のステップと同様に、次の関数を todolist todolist コンポーネントに追加します。この関数は deletetodomutation deletetodomutation を呼び出し、後でボタンによって参照されます。 1 const deletetodo = (todoid) => { 2 const input = { 3 id todoid, 4 } 5	 6 deletetodomutation commit({ 7 environment, 8 input input, 9 oncompleted () => { 10 alert alert('success!', 'todo deleted!'); 11 }, 12 onerror (errors) => { 13 alert alert('error!', errors); 14 }, 15 }); 16 } 7 react nativeコンポーネントでのcrudの使用 では、スタイル付きのユーザーインターフェース要素、状態変数、およびcrud関数への呼び出しを含む、私たちの todolist todolist コンポーネントコードを完成させましょう。 1 import react, {usestate} from 'react'; 2 import { 3 alert, 4 view, 5 safeareaview, 6 image, 7 scrollview, 8 statusbar, 9 stylesheet, 10 touchableopacity, 11 } from 'react native'; 12	 13 import { 14 list, 15 text as papertext, 16 button as paperbutton, 17 textinput as papertextinput, 18 } from 'react native paper'; 19 import {createfragmentcontainer} from 'react relay'; 20 import createtodomutation from ' /mutations/createtodomutation'; 21 import updatetodomutation from ' /mutations/updatetodomutation'; 22 import deletetodomutation from ' /mutations/deletetodomutation'; 23	 24 import environment from ' / /relay/environment'; 25	 26 const todolist = props => { 27 const \[newtodotitle, setnewtodotitle] = usestate(''); 28	 29 const {query} = props; 30 const {todos} = query; 31	 32 const createtodo = () => { 33 const input = { 34 fields { 35 title newtodotitle, 36 done false, 37 }, 38 }; 39	 40 createtodomutation commit({ 41 environment, 42 input input, 43 oncompleted () => { 44 alert alert('success!', 'todo created!'); 45 setnewtodotitle(''); 46 }, 47 onerror errors => { 48 alert alert('error!', errors); 49 }, 50 }); 51 }; 52	 53 const updatetodo = (todoid, done) => { 54 const input = { 55 id todoid, 56 fields { 57 done, 58 }, 59 }; 60	 61 updatetodomutation commit({ 62 environment, 63 input input, 64 oncompleted () => { 65 alert alert('success!', 'todo updated!'); 66 }, 67 onerror errors => { 68 alert alert('error!', errors); 69 }, 70 }); 71 }; 72	 73 const deletetodo = todoid => { 74 const input = { 75 id todoid, 76 }; 77	 78 deletetodomutation commit({ 79 environment, 80 input input, 81 oncompleted () => { 82 alert alert('success!', 'todo deleted!'); 83 }, 84 onerror errors => { 85 alert alert('error!', errors); 86 }, 87 }); 88 }; 89	 90 const rendertodos = () => { 91 if (!todos) { 92 return null; 93 } 94	 95 return todos edges map(({node todo}) => ( 96 \<list item 97 key={todo id} 98 title={todo title} 99 titlestyle={todo done ? styles todo text done styles todo text} 100 style={styles todo item} 101 right={props => ( 102 <> 103 {!todo done && ( 104 \<touchableopacity onpress={() => updatetodo(todo id, true)}> 105 \<list icon { props} icon="check" color={'#4caf50'} /> 106 \</touchableopacity> 107 )} 108	 109 \<touchableopacity onpress={() => deletetodo(todo id)}> 110 \<list icon { props} icon="close" color={'#ef5350'} /> 111 \</touchableopacity> 112 \</> 113 )} 114 /> 115 )); 116 }; 117	 118 return ( 119 <> 120 \<statusbar backgroundcolor="#208aec" /> 121 \<safeareaview style={styles container}> 122 \<view style={styles header}> 123 \<image 124 style={styles header logo} 125 source={ { 126 uri 127 'https //blog back4app com/wp content/uploads/2019/05/back4app white logo 500px png', 128 } } 129 /> 130 \<papertext style={styles header text bold}> 131 {'react native on back4app'} 132 \</papertext> 133 \<papertext style={styles header text}>{'product creation'}\</papertext> 134 \</view> 135 \<view style={styles create todo container}> 136 {/ todo create text input /} 137 \<papertextinput 138 value={newtodotitle} 139 onchangetext={text => setnewtodotitle(text)} 140 label="new todo" 141 mode="outlined" 142 style={styles create todo input} 143 /> 144 {/ todo create button /} 145 \<paperbutton 146 onpress={() => createtodo()} 147 mode="contained" 148 icon="plus" 149 color={'#208aec'} 150 style={styles create todo button}> 151 {'add'} 152 \</paperbutton> 153 \</view> 154 \<scrollview style={styles todo list}>{rendertodos()}\</scrollview> 155 \</safeareaview> 156 \</> 157 ); 158 }; 159	 160 const todolistfragmentcontainer = createfragmentcontainer(todolist, { 161 query graphql` 162 fragment todolist query on query { 163 todos(first 1000) @connection(key "todolist todos", filters \[]) { 164 edges { 165 node { 166 id 167 title 168 done 169 } 170 } 171 } 172 } 173 `, 174 }); 175	 176 const styles = stylesheet create({ 177 container { 178 flex 1, 179 backgroundcolor '#fff', 180 }, 181 wrapper { 182 width '90%', 183 alignself 'center', 184 }, 185 header { 186 alignitems 'center', 187 paddingtop 10, 188 paddingbottom 20, 189 backgroundcolor '#208aec', 190 }, 191 header logo { 192 width 170, 193 height 40, 194 marginbottom 10, 195 resizemode 'contain', 196 }, 197 header text bold { 198 color '#fff', 199 fontsize 14, 200 fontweight 'bold', 201 }, 202 header text { 203 margintop 3, 204 color '#fff', 205 fontsize 14, 206 }, 207 flex between { 208 flexdirection 'row', 209 alignitems 'center', 210 justifycontent 'space between', 211 }, 212 create todo container { 213 flexdirection 'row', 214 paddingleft 10, 215 paddingright 10, 216 }, 217 create todo input { 218 flex 1, 219 height 38, 220 marginbottom 16, 221 backgroundcolor '#fff', 222 fontsize 14, 223 }, 224 create todo button { 225 margintop 6, 226 marginleft 15, 227 height 40, 228 }, 229 todo list { 230 paddingleft 10, 231 paddingright 10, 232 }, 233 todo item { 234 borderbottomwidth 1, 235 borderbottomcolor 'rgba(0, 0, 0, 0 12)', 236 }, 237 todo text { 238 fontsize 15, 239 }, 240 todo text done { 241 color 'rgba(0, 0, 0, 0 3)', 242 fontsize 15, 243 textdecorationline 'line through', 244 }, 245 }); 246	 247 export default todolistfragmentcontainer; プロジェクトを実行する前に、忘れずに yarn relay yarn relay を実行し、relay generated generated タイプを更新してください コンポーネントが正しく設定されていれば、アプリをビルドして実行した後にこのようなものが表示されるはずです 続けて、入力ボックスにタイトルを1つずつ入力し、追加ボタンを押していくことで、いくつかのto doを追加してください。すべての成功した作成の後に、 createtodo createtodo 関数がミューテーション内のアップデータコールバックをトリガーし、タスクリストを自動的に更新します。これで、次のような大きなto doリストができているはずです タスクを完了としてマークするには、その横にあるチェックマークをクリックすることで、完了値がtrueに更新され、左側のアイコンの状態が変更されます。更新関数のステップで述べたように、relayは自動的にtodoをフィールドの新しい値で更新します。 完了 完了 残っているデータ操作は削除のみで、これはあなたのto doリストオブジェクトの最右にあるゴミ箱アイコンを押すことで行えます。オブジェクトを正常に削除した後、次のようなアラートメッセージが表示されるはずです 結論 このガイドの最後に、react native上でgrapqhqlとrelay modernを使用して基本的なデータ操作(crud)を実行する方法を学び、フロントエンドを更新するのに役立つrelay connection apiについても学びました。