ReactJS
Data objects
Geoqueries em React com Parse: Orientações Técnicas Avançadas
10 min
usando geolocalização do react para realizar geoqueries com parse introdução neste guia, você realizará geoqueries no parse usando a geolocalização do react você implementará um componente react usando essas consultas e aprenderá como configurar e consultar dados realistas usando back4app e react pré requisitos para completar este tutorial, você precisará um aplicativo react criado e https //www back4app com/docs/react/quickstart se você quiser executar o projeto de exemplo deste guia, deve configurar a https //ant design/ objetivo realizar geoqueries usando geopoints armazenados no back4app e geolocalização do react 1 entendendo a classe parse query qualquer operação de consulta do parse usa o parse query parse query tipo de objeto, que ajudará você a recuperar dados específicos do seu banco de dados ao longo do seu aplicativo é crucial saber que um parse query parse query só será resolvido após chamar um método de recuperação (como parse query find parse query find ou parse query get parse query get ), então uma consulta pode ser configurada e vários modificadores podem ser encadeados antes de realmente serem chamados para criar um novo parse query parse query , você precisa passar como parâmetro a desejada parse object parse object subclasse, que é a que conterá os resultados da sua consulta um exemplo de consulta pode ser visto abaixo, na qual uma profile profile subclasse fictícia está sendo consultada 1 // this will create your query 2 let parsequery = new parse query("profile"); 3 // the query will resolve only after calling this method 4 let queryresult = await parsequery find(); você pode ler mais sobre a parse query parse query classe https //parseplatform org/parse sdk js/api/master/parse query html 2 salvar alguns dados no back4app vamos criar uma city city classe, que será o alvo de nossas consultas neste guia no console js do parse, é possível executar código javascript diretamente, consultando e atualizando o conteúdo do banco de dados da sua aplicação usando os comandos do sdk js execute o código abaixo no seu console js e insira os dados no back4app aqui está como o console js se parece no seu painel vá em frente e crie a cidade cidade classe com o seguinte conteúdo de exemplo 1 // add city objects and create table 2 // note how geopoints are created, passing latitude and longitude as arguments 3 // montevideo 4 var city = new parse object('city'); 5 city set('name', 'montevideo uruguay'); 6 city set('location', new parse geopoint( 34 85553195363169, 56 207280375137955)); 7 await city save(); 8	 9 // brasília 10 city = new parse object('city'); 11 city set('name', 'brasília brazil'); 12 city set('location', new parse geopoint( 15 79485821477289, 47 88391074690196)); 13 await city save(); 14	 15 // bogotá 16 city = new parse object('city'); 17 city set('name', 'bogotá colombia'); 18 city set('location', new parse geopoint(4 69139880891712, 74 06936691331047)); 19 await city save(); 20	 21 // mexico city 22 city = new parse object('city'); 23 city set('name', 'mexico city mexico'); 24 city set('location', new parse geopoint(19 400977162618933, 99 13311378164776)); 25 await city save(); 26	 27 // washington, d c 28 city = new parse object('city'); 29 city set('name', 'washington, d c usa'); 30 city set('location', new parse geopoint(38 930727220189944, 77 04626261880388)); 31 await city save(); 32	 33 // ottawa 34 city = new parse object('city'); 35 city set('name', 'ottawa canada'); 36 city set('location', new parse geopoint(45 41102167733425, 75 695414598736)); 37 await city save(); 38	 39 console log('success!'); 3 consultar os dados agora que você tem uma classe populada, podemos realizar algumas consultas geopoint nela vamos começar ordenando cidade cidade os resultados pelo mais próximo de kingston na jamaica (latitude 18 01808695059913 e longitude 76 79894232253473), usando o parse query near parse query near método 1 // create your query 2 let parsequery = new parse query('city'); 3	 4 // create our geopoint for the query 5 let kingstongeopoint = new parse geopoint(18 018086950599134, 76 79894232253473); 6	 7 // `near` will order results based on distance between the geopoint type field from the class and the geopoint argument 8 parsequery near('location', kingstongeopoint); 9	 10 // the query will resolve only after calling this method, retrieving 11 // an array of `parse objects` 12 let queryresults = await parsequery find(); 13	 14 // let's show the results 15 for (let result of queryresults) { 16 // you access `parse objects` attributes by using ` get` 17 console log(result get('name')); 18 }; agora vamos consultar usando o método parse query withinkilometers parse query withinkilometers , que irá recuperar todos os resultados cujo campo geopoint está localizado dentro da distância máxima kingston será usado mais uma vez como referência e o limite de distância será de 3000 km 1 // create your query 2 let parsequery = new parse query('city'); 3	 4 // create our geopoint for the query 5 let kingstongeopoint = new parse geopoint(18 018086950599134, 76 79894232253473); 6	 7 // you can also use `withinmiles` and `withinradians` the same way, 8 // but with different measuring unities 9 parsequery withinkilometers('location', kingstongeopoint, 3000); 10	 11 // the query will resolve only after calling this method, retrieving 12 // an array of `parse objects` 13 let queryresults = await parsequery find(); 14	 15 // let's show the results 16 for (let result of queryresults) { 17 // you access `parse objects` attributes by using ` get` 18 console log(result get('name')); 19 }; outro método de consulta útil é parse query withinpolygon parse query withinpolygon , que irá consultar resultados cujo valor do campo geopoint esteja dentro do polígono especificado, composto por um array de geopoints (pelo menos três) se o caminho do polígono estiver aberto, ele será fechado automaticamente pelo parse conectando os últimos e primeiros pontos para este exemplo, você usará um polígono simples que contém aproximadamente o continente sul americano, composto por 5 geopoints distantes no oceano 1 // create your query 2 let parsequery = new parse query('city'); 3	 4 // create our geopoint polygon for the query 5 let geopoint1 = new parse geopoint(15 822238344514378, 72 42845934415942); 6 let geopoint2 = new parse geopoint( 0 7433770196268968, 97 44765968406668); 7 let geopoint3 = new parse geopoint( 59 997149373299166, 76 52969196322749); 8 let geopoint4 = new parse geopoint( 9 488786415007201, 18 346101586021952); 9 let geopoint5 = new parse geopoint(15 414859532811047, 60 00625459569375); 10	 11 // note that the polygon is merely an array of geopoint objects and that the first and last are not connected, so parse connects them for you 12 parsequery withinpolygon('location', \[geopoint1, geopoint2, geopoint3, geopoint4, geopoint5]); 13	 14 // the query will resolve only after calling this method, retrieving 15 // an array of `parse objects` 16 let queryresults = await parsequery find(); 17	 18 // let's show the results 19 for (let result of queryresults) { 20 // you access `parse objects` attributes by using ` get` 21 console log(result get('name')); 22 }; 4 consulta a partir de um componente react vamos agora usar nossas consultas de exemplo dentro de um componente em react, com uma interface simples que possui uma lista mostrando os resultados e também 3 botões para chamar as consultas o componente também recupera a localização atual do dispositivo usando o navigator geolocation navigator geolocation api javascript, então as consultas usarão dados reais, desde que o usuário não tenha desativado o acesso à localização no navegador assim é como o código do componente está estruturado, note as doquery doquery funções, contendo o código de exemplo da forma anterior javascript 1 import react, { usestate } from 'react'; 2 import parse from 'parse/dist/parse min js'; 3 import ' /app css'; 4 import { button, divider } from 'antd'; 5 import { closeoutlined, searchoutlined } from '@ant design/icons'; 6	 7 export const querygeo = () => { 8 // state variable 9 const \[queryresults, setqueryresults] = usestate(); 10	 11 const doquerynear = async function () { 12 // check if geolocation api is available in the browser 13 if ('geolocation' in navigator) { 14 // get current location and create the geopoint for the query 15 navigator geolocation getcurrentposition( 16 async function (position) { 17 const currentposition = { 18 latitude position coords latitude, 19 longitude position coords longitude, 20 }; 21 // create our geopoint 22 let currentlocationgeopoint = new parse geopoint( 23 currentposition latitude, 24 currentposition longitude 25 ); 26	 27 // create our query 28 let parsequery = new parse query('city'); 29	 30 // `near` will order results based on distance between the geopoint type field from the class and the geopoint argument 31 parsequery near('location', currentlocationgeopoint); 32	 33 try { 34 let results = await parsequery find(); 35 // set query results to state variable 36 setqueryresults(results); 37 return true; 38 } catch (error) { 39 // error can be caused by lack of internet connection 40 alert(`error! ${error message}`); 41 } 42 }, 43 function ( error) { 44 alert( 45 'you need to allow geolocation to retrieve your location on the browser to test this if you are on an apple os, enable it on your system preferences ' 46 ); 47 } 48 ); 49 } else { 50 alert('geolocation services are not supported by your browser '); 51 } 52 return false; 53 }; 54	 55 const doquerywithinkilometers = async function () { 56 // check if geolocation api is available in the browser 57 if ('geolocation' in navigator) { 58 // get current location and create the geopoint for the query 59 navigator geolocation getcurrentposition( 60 async function (position) { 61 const currentposition = { 62 latitude position coords latitude, 63 longitude position coords longitude, 64 }; 65 // create our geopoint 66 let currentlocationgeopoint = new parse geopoint( 67 currentposition latitude, 68 currentposition longitude 69 ); 70	 71 // create our query 72 let parsequery = new parse query('city'); 73	 74 // you can also use `withinmiles` and `withinradians` the same way, 75 // but with different measuring unities 76 parsequery withinkilometers( 77 'location', 78 currentlocationgeopoint, 79 3000 80 ); 81	 82 try { 83 let results = await parsequery find(); 84 // set query results to state variable 85 setqueryresults(results); 86 } catch (error) { 87 // error can be caused by lack of internet connection 88 alert(`error! ${error message}`); 89 } 90 }, 91 function ( error) { 92 alert( 93 'you need to allow geolocation to retrieve your location on the browser to test this if you are on an apple os, enable it on your system preferences ' 94 ); 95 } 96 ); 97 } else { 98 alert('geolocation services are not supported by your browser '); 99 } 100 return false; 101 }; 102	 103 const doquerywithinpolygon = async function () { 104 // create our geopoint polygon points 105 let geopoint1 = new parse geopoint(15 822238344514378, 72 42845934415942); 106 let geopoint2 = new parse geopoint( 0 7433770196268968, 97 44765968406668); 107 let geopoint3 = new parse geopoint( 59 997149373299166, 76 52969196322749); 108 let geopoint4 = new parse geopoint( 9 488786415007201, 18 346101586021952); 109 let geopoint5 = new parse geopoint(15 414859532811047, 60 00625459569375); 110	 111 // create our query 112 let parsequery = new parse query('city'); 113	 114 // note that the polygon is merely an array of geopoint objects and that the first and 115 // last are not connected, so parse connects them for you 116 parsequery withinpolygon('location', \[ 117 geopoint1, 118 geopoint2, 119 geopoint3, 120 geopoint4, 121 geopoint5, 122 ]); 123	 124 try { 125 let results = await parsequery find(); 126 // set query results to state variable 127 setqueryresults(results); 128 } catch (error) { 129 // error can be caused by lack of internet connection 130 alert(`error! ${error}`); 131 return false; 132 } 133 return true; 134 }; 135	 136 const clearqueryresults = async function () { 137 setqueryresults(undefined); 138 return true; 139 }; 140	 141 return ( 142 \<div> 143 \<div classname="header"> 144 \<img 145 classname="header logo" 146 alt="back4app logo" 147 src={ 148 'https //blog back4app com/wp content/uploads/2019/05/back4app white logo 500px png' 149 } 150 /> 151 \<p classname="header text bold">{'react on back4app'}\</p> 152 \<p classname="header text">{'geopoint queries'}\</p> 153 \</div> 154 \<div classname="container"> 155 \<div classname="flex between"> 156 \<h2 classname="heading">{'query list'}\</h2> 157 \<div classname="flex"> 158 \<button 159 onclick={() => doquerynear()} 160 type="primary" 161 classname="heading button" 162 color={'#208aec'} 163 icon={\<searchoutlined />} 164 > 165 query near 166 \</button> 167 \<button 168 onclick={() => doquerywithinkilometers()} 169 type="primary" 170 classname="heading button" 171 color={'#208aec'} 172 icon={\<searchoutlined />} 173 > 174 query within km 175 \</button> 176 \<button 177 onclick={() => doquerywithinpolygon()} 178 type="primary" 179 classname="heading button" 180 color={'#208aec'} 181 icon={\<searchoutlined />} 182 > 183 query within polygon 184 \</button> 185 \<button 186 onclick={() => clearqueryresults()} 187 type="primary" 188 classname="heading button" 189 color={'#208aec'} 190 icon={\<closeoutlined />} 191 > 192 clear results 193 \</button> 194 \</div> 195 \</div> 196 \<divider /> 197 \<div classname="flex between"> 198 \<div classname="flex child"> 199 {/ query list /} 200 {queryresults !== undefined && 201 queryresults map((result, index) => ( 202 \<div classname="list item" key={`${index}`}> 203 \<p classname="list item title">{`${result get('name')}`}\</p> 204 \</div> 205 ))} 206 {queryresults !== undefined && queryresults length <= 0 ? ( 207 \<p>{'no results here!'}\</p> 208 ) null} 209 \</div> 210 \</div> 211 \</div> 212 \</div> 213 ); 214 }; typescript 1 import react, { usestate, fc, reactelement } from 'react'; 2 import ' /app css'; 3 import { button, divider } from 'antd'; 4 import { closeoutlined, searchoutlined } from '@ant design/icons'; 5 const parse = require('parse/dist/parse min js'); 6	 7 type locationobject = {latitude number, longitude number}; 8	 9 export const querygeo fc<{}> = () reactelement => { 10 // state variable 11 const \[queryresults, setqueryresults] = usestate\<parse object\[]>(); 12	 13 const doquerynear = async function () promise\<boolean> { 14 // check if geolocation api is available in the browser 15 if ("geolocation" in navigator) { 16 // get current location and create the geopoint for the query 17 navigator geolocation getcurrentposition(async function (position) { 18 const currentposition locationobject = { latitude position coords latitude, longitude position coords longitude }; 19 // create our geopoint 20 let currentlocationgeopoint parse geopoint = new parse geopoint( 21 currentposition latitude, 22 currentposition longitude, 23 ); 24	 25 // create our query 26 let parsequery parse query = new parse query('city'); 27	 28 // `near` will order results based on distance between the geopoint type field from the class and the geopoint argument 29 parsequery near('location', currentlocationgeopoint); 30	 31 try { 32 let results parse object\[] = await parsequery find(); 33 // set query results to state variable 34 setqueryresults(results); 35 return true; 36 } catch (error) { 37 // error can be caused by lack of internet connection 38 alert(`error! ${error message}`); 39 } 40 }, function ( error any) { 41 alert("you need to allow geolocation to retrieve your location on the browser to test this if you are on an apple os, enable it on your system preferences "); 42 }); 43 } else { 44 alert("geolocation services are not supported by your browser "); 45 } 46 return false; 47 }; 48	 49 const doquerywithinkilometers = async function () promise\<boolean> { 50 // check if geolocation api is available in the browser 51 if ("geolocation" in navigator) { 52 // get current location and create the geopoint for the query 53 navigator geolocation getcurrentposition(async function (position) { 54 const currentposition locationobject = { latitude position coords latitude, longitude position coords longitude }; 55 // create our geopoint 56 let currentlocationgeopoint parse geopoint = new parse geopoint( 57 currentposition latitude, 58 currentposition longitude, 59 ); 60	 61 // create our query 62 let parsequery parse query = new parse query('city'); 63	 64 // you can also use `withinmiles` and `withinradians` the same way, 65 // but with different measuring unities 66 parsequery withinkilometers('location', currentlocationgeopoint, 3000); 67	 68 try { 69 let results parse object\[] = await parsequery find(); 70 // set query results to state variable 71 setqueryresults(results); 72 } catch (error) { 73 // error can be caused by lack of internet connection 74 alert(`error! ${error message}`); 75 } 76 }, function ( error any) { 77 alert("you need to allow geolocation to retrieve your location on the browser to test this if you are on an apple os, enable it on your system preferences "); 78 }); 79 } else { 80 alert("geolocation services are not supported by your browser "); 81 } 82 return false; 83 }; 84	 85 const doquerywithinpolygon = async function () promise\<boolean> { 86 // create our geopoint polygon points 87 // in react typescript types ('@types/parse'), parse query withinpolygon expects 88 // an array of number arrays, so you need to change the declarations 89 let geopoint1 number\[] = \[ 90 7 242 845 934 415 940,00 91 15 822 238 344 514 300,00 92 ]; 93 let geopoint2 number\[] = \[ 94 9 744 765 968 406 660,00 95 0 7433770196268968, 96 ]; 97 let geopoint3 number\[] = \[ 98 7 652 969 196 322 740,00 99 59 997 149 373 299 100,00 100 ]; 101 let geopoint4 number\[] = \[ 102 18 346 101 586 021 900,00 103 9 488 786 415 007 200,00 104 ]; 105 let geopoint5 number\[] = \[ 106 6 000 625 459 569 370,00 107 15 414 859 532 811 000,00 108 ]; 109	 110 // create our query 111 let parsequery parse query = new parse query('city'); 112	 113 // note that the polygon is merely an array of geopoint objects and that the first and 114 // last are not connected, so parse connects them for you 115 parsequery withinpolygon('location', \[ 116 geopoint1, 117 geopoint2, 118 geopoint3, 119 geopoint4, 120 geopoint5, 121 ]); 122	 123 try { 124 let results parse object\[] = await parsequery find(); 125 // set query results to state variable 126 setqueryresults(results); 127 } catch (error) { 128 // error can be caused by lack of internet connection 129 alert(`error! ${error}`); 130 return false; 131 } 132 return true; 133 }; 134	 135 const clearqueryresults = async function () promise\<boolean> { 136 setqueryresults(undefined); 137 return true; 138 }; 139	 140 return ( 141 \<div> 142 \<div classname="header"> 143 \<img 144 classname="header logo" 145 alt="back4app logo" 146 src={ 147 'https //blog back4app com/wp content/uploads/2019/05/back4app white logo 500px png' 148 } 149 /> 150 \<p classname="header text bold">{'react on back4app'}\</p> 151 \<p classname="header text">{'geopoint queries'}\</p> 152 \</div> 153 \<div classname="container"> 154 \<div classname="flex between"> 155 \<h2 classname="heading">{'query list'}\</h2> 156 \<div classname="flex"> 157 \<button 158 onclick={() => doquerynear()} 159 type="primary" 160 classname="heading button" 161 color={'#208aec'} 162 icon={\<searchoutlined />} 163 > 164 query near 165 \</button> 166 \<button 167 onclick={() => doquerywithinkilometers()} 168 type="primary" 169 classname="heading button" 170 color={'#208aec'} 171 icon={\<searchoutlined />} 172 > 173 query within km 174 \</button> 175 \<button 176 onclick={() => doquerywithinpolygon()} 177 type="primary" 178 classname="heading button" 179 color={'#208aec'} 180 icon={\<searchoutlined />} 181 > 182 query within polygon 183 \</button> 184 \<button 185 onclick={() => clearqueryresults()} 186 type="primary" 187 classname="heading button" 188 color={'#208aec'} 189 icon={\<closeoutlined />} 190 > 191 clear results 192 \</button> 193 \</div> 194 \</div> 195 \<divider /> 196 \<div classname="flex between"> 197 \<div classname="flex child"> 198 {/ query list /} 199 {queryresults !== undefined && 200 queryresults map((result parse object, index number) => ( 201 \<div classname="list item" key={`${index}`}> 202 \<p classname="list item title">{`${result get('name')}`}\</p> 203 \</div> 204 ))} 205 {queryresults !== undefined && 206 queryresults length <= 0 ? ( 207 \<p>{'no results here!'}\</p> 208 ) null} 209 \</div> 210 \</div> 211 \</div> 212 \</div> 213 ); 214 }; adicione também essas classes ao seu app css app css arquivo para renderizar completamente o layout do componente app css 1 html { 2 box sizing border box; 3 outline none; 4 overflow auto; 5 } 6	 7 , 8 before, 9 after { 10 margin 0; 11 padding 0; 12 box sizing inherit; 13 } 14	 15 h1, 16 h2, 17 h3, 18 h4, 19 h5, 20 h6 { 21 margin 0; 22 font weight bold; 23 } 24	 25 p { 26 margin 0; 27 } 28	 29 body { 30 margin 0; 31 background color #fff; 32 } 33	 34 container { 35 width 100%; 36 max width 900px; 37 margin auto; 38 padding 20px 0; 39 text align left; 40 } 41	 42 header { 43 align items center; 44 padding 25px 0; 45 background color #208aec; 46 } 47	 48 header logo { 49 height 55px; 50 margin bottom 20px; 51 object fit contain; 52 } 53	 54 header text bold { 55 margin bottom 3px; 56 color rgba(255, 255, 255, 0 9); 57 font size 16px; 58 font weight bold; 59 } 60	 61 header text { 62 color rgba(255, 255, 255, 0 9); 63 font size 15px; 64 } 65	 66 heading { 67 font size 22px; 68 } 69	 70 flex { 71 display flex; 72 } 73	 74 flex between { 75 display flex; 76 justify content space between; 77 } 78	 79 flex child { 80 flex 0 0 45%; 81 } 82	 83 heading button { 84 margin left 12px; 85 } 86	 87 list item { 88 padding bottom 15px; 89 margin bottom 15px; 90 border bottom 1px solid rgba(0,0,0,0 06); 91 text align left; 92 } 93	 94 list item title { 95 color rgba(0,0,0,0 87); 96 font size 17px; 97 } é assim que o componente deve parecer após a renderização e a consulta de uma das funções de consulta conclusão no final deste guia, você aprendeu como funcionam as consultas de dados geopoint no parse e como realizá las no back4app a partir de uma aplicação react no próximo guia, você verá como criar e gerenciar usuários no parse