ReactJS
Users
Интеграция входа через Google в React с использованием Parse
9 мин
вход через google в react введение в последнем уроке вы создали функцию входа/выхода пользователя в ваше приложение, используя класс parse user parse user теперь вы узнаете, как использовать вход через google для получения данных пользователя из google и входа, регистрации или связывания существующих пользователей с ним вы также установите и настроите библиотеку react google login react google login , чтобы достичь этого метод parse user linkwith parse user linkwith отвечает за регистрацию и вход пользователей, используя любой метод аутентификации третьих сторон, при условии, что вы передаете правильные параметры, запрашиваемые каждым различным провайдером после связывания данных пользователя с новым или существующим parse user parse user , parse сохранит действительную сессию пользователя на вашем устройстве будущие вызовы методов, таких как current current , успешно извлекут ваши данные пользователя, так же как и при обычных входах предварительные требования чтобы завершить этот урок, вам потребуется созданное приложение react и подключенное к back4app завершите предыдущий гид, чтобы лучше понять класс parse user и метод parse user login https //www back4app com/docs/react/working with users/react user login если вы хотите протестировать/использовать макет экрана, предоставленный этим руководством, вам следует установить библиотеку ant design ant design цель создать функцию входа пользователя с использованием входа через google на parse для приложения react 1 установка зависимостей самый популярный способ включить вход через google в react использовать react google login react google login для обработки этого настройте его, следуя официальной документации убедитесь, что вы создали oauth clientid clientid на странице учетных данных google, добавив ваш локальный адрес разработки в авторизованные url, который обычно является http //localhost 3000 http //localhost 3000 2 использование входа через google с parse теперь давайте создадим новый метод внутри userlogin userlogin компонента, который будет обрабатывать ответ при вызове модального окна аутентификации google sign in если пользователь войдет в систему с помощью google, этот вызов получит данные пользователя из google, и вам нужно будет сохранить id, idtoken idtoken , и электронную почту google затем функция попытается войти в систему на parse, используя метод parse user linkwith parse user linkwith и эти учетные данные обратите внимание, что если ваш пользователь уже зарегистрировался с помощью этой аутентификации google, linkwith linkwith войдет в систему, используя существующую учетную запись javascript 1 const handlegoogleloginloginresponse = async function(response) { 2 // check if response has an error 3 if (response error !== undefined) { 4 console log(`error ${response error}`); 5 return false; 6 } else { 7 try { 8 // gather google user info 9 const usergoogleid = response googleid; 10 const usertokenid = response tokenid; 11 const useremail = response profileobj email; 12 // try to login on parse using linkwith and these credentials 13 // create a new parse user object 14 const usertologin = new parse user(); 15 // set username and email to match google email 16 usertologin set('username', useremail); 17 usertologin set('email', useremail); 18 try { 19 let loggedinuser = await usertologin 20 linkwith('google', { 21 authdata {id usergoogleid, id token usertokenid}, 22 }); 23 // login returns the corresponding parseuser object 24 alert( 25 `success! user ${loggedinuser get('username')} has successfully signed in!`, 26 ); 27 // update state variable holding current user 28 getcurrentuser(); 29 return true; 30 } catch (error) { 31 // error can be caused by wrong parameters or lack of internet connection 32 alert(`error! ${error message}`); 33 return false; 34 } 35 } catch (error) { 36 console log("error gathering google user info, please try again!") 37 return false; 38 } 39 } 40 }1 const handlegoogleloginloginresponse = async function(response any) promise\<boolean> { 2 // check if response has an error 3 if (response error !== undefined) { 4 console log(`error ${response error}`); 5 return false; 6 } else { 7 try { 8 // gather google user info 9 const usergoogleid string = response googleid; 10 const usertokenid string = response tokenid; 11 const useremail string = response profileobj email; 12 // try to login on parse using linkwith and these credentials 13 // create a new parse user object 14 const usertologin parse user = new parse user(); 15 // set username and email to match google email 16 usertologin set('username', useremail); 17 usertologin set('email', useremail); 18 try { 19 let loggedinuser parse user = await usertologin 20 linkwith('google', { 21 authdata {id usergoogleid, id token usertokenid}, 22 }); 23 // login returns the corresponding parseuser object 24 alert( 25 `success! user ${loggedinuser get('username')} has successfully signed in!`, 26 ); 27 // update state variable holding current user 28 getcurrentuser(); 29 return true; 30 } catch (error any) { 31 // error can be caused by wrong parameters or lack of internet connection 32 alert(`error! ${error message}`); 33 return false; 34 } 35 } catch (error any) { 36 console log("error gathering google user info, please try again!") 37 return false; 38 } 39 } 40 } после этого вам нужно использовать react google login react google login googlelogin googlelogin компонент, чтобы вызвать модальное окно google signin, добавив его в ваш jsx код вы можете использовать стандартное оформление от google или создать собственное, что и является подходом, описанным в этом руководстве вот полный код компонента userlogin userlogin компонента, обратите внимание на react google login react google login кнопку и то, как она связана с методом ответа модального окна, созданным ранее javascript 1 import react, { usestate } from 'react'; 2 import parse from 'parse/dist/parse min js'; 3 import googlelogin from 'react google login'; 4 import ' /app css'; 5 import { button, divider, input } from 'antd'; 6	 7 export const userlogin = () => { 8 // state variables 9 const \[username, setusername] = usestate(''); 10 const \[password, setpassword] = usestate(''); 11 const \[currentuser, setcurrentuser] = usestate(null); 12	 13 const douserlogin = async function () { 14 // note that these values come from state variables that we've declared before 15 const usernamevalue = username; 16 const passwordvalue = password; 17 try { 18 const loggedinuser = await parse user login(usernamevalue, passwordvalue); 19 // login returns the corresponding parseuser object 20 alert( 21 `success! user ${loggedinuser get( 22 'username' 23 )} has successfully signed in!` 24 ); 25 // to verify that this is in fact the current user, `current` can be used 26 const currentuser = await parse user current(); 27 console log(loggedinuser === currentuser); 28 // clear input fields 29 setusername(''); 30 setpassword(''); 31 // update state variable holding current user 32 getcurrentuser(); 33 return true; 34 } catch (error) { 35 // error can be caused by wrong parameters or lack of internet connection 36 alert(`error! ${error message}`); 37 return false; 38 } 39 }; 40	 41 const douserlogout = async function () { 42 try { 43 await parse user logout(); 44 // to verify that current user is now empty, currentasync can be used 45 const currentuser = await parse user current(); 46 if (currentuser === null) { 47 alert('success! no user is logged in anymore!'); 48 } 49 // update state variable holding current user 50 getcurrentuser(); 51 return true; 52 } catch (error) { 53 alert(`error! ${error message}`); 54 return false; 55 } 56 }; 57	 58 // function that will return current user and also update current username 59 const getcurrentuser = async function () { 60 const currentuser = await parse user current(); 61 // update state variable holding current user 62 setcurrentuser(currentuser); 63 return currentuser; 64 }; 65	 66 const handlegoogleloginloginresponse = async function (response) { 67 // check if response has an error 68 if (response error !== undefined) { 69 console log(`error ${response error}`); 70 return false; 71 } else { 72 try { 73 // gather google user info 74 const usergoogleid = response googleid; 75 const usertokenid = response tokenid; 76 const useremail = response profileobj email; 77 // try to login on parse using linkwith and these credentials 78 // create a new parse user object 79 const usertologin = new parse user(); 80 // set username and email to match google email 81 usertologin set('username', useremail); 82 usertologin set('email', useremail); 83 try { 84 let loggedinuser = await usertologin linkwith('google', { 85 authdata { id usergoogleid, id token usertokenid }, 86 }); 87 // login returns the corresponding parseuser object 88 alert( 89 `success! user ${loggedinuser get( 90 'username' 91 )} has successfully signed in!` 92 ); 93 // update state variable holding current user 94 getcurrentuser(); 95 return true; 96 } catch (error) { 97 // error can be caused by wrong parameters or lack of internet connection 98 alert(`error! ${error message}`); 99 return false; 100 } 101 } catch (error) { 102 console log('error gathering google user info, please try again!'); 103 return false; 104 } 105 } 106 }; 107	 108 return ( 109 \<div> 110 \<div classname="header"> 111 \<img 112 classname="header logo" 113 alt="back4app logo" 114 src={ 115 'https //blog back4app com/wp content/uploads/2019/05/back4app white logo 500px png' 116 } 117 /> 118 \<p classname="header text bold">{'react on back4app'}\</p> 119 \<p classname="header text">{'user login'}\</p> 120 \</div> 121 {currentuser === null && ( 122 \<div classname="container"> 123 \<h2 classname="heading">{'user login'}\</h2> 124 \<divider /> 125 \<div classname="form wrapper"> 126 \<input 127 value={username} 128 onchange={(event) => setusername(event target value)} 129 placeholder="username" 130 size="large" 131 classname="form input" 132 /> 133 \<input 134 value={password} 135 onchange={(event) => setpassword(event target value)} 136 placeholder="password" 137 size="large" 138 type="password" 139 classname="form input" 140 /> 141 \</div> 142 \<div classname="form buttons"> 143 \<button 144 onclick={() => douserlogin()} 145 type="primary" 146 classname="form button" 147 color={'#208aec'} 148 size="large" 149 block 150 > 151 log in 152 \</button> 153 \</div> 154 \<divider /> 155 \<div classname="login social"> 156 \<div classname="login social item login social item facebook"> 157 \<img classname="login social item image" src={'https //findicons com/files/icons/2830/clean social icons/250/facebook png'} alt=""/> 158 \</div> 159 \<googlelogin 160 clientid="108490793456 0flm4qh8ek4cb4krt7e06980o4sjvado apps googleusercontent com" 161 render={renderprops => ( 162 \<div classname="login social item"> 163 \<img onclick={renderprops onclick} classname="login social item image" src={'data\ image/png;base64,ivborw0kggoaaaansuheugaaan8aaadicamaaad5w+jtaaabwvbmvex////qqzu0qfnchft7vauufppk7f08gvr0o/zzofb7uqd7uadpncp/vqdqpzaspk7plhrpoysyoklpoyzpnst97ovwgnskpensxfh8wgavouhplrj+9/b0pad4xsoix5fd7+h74udvenlru0f61tt1r6vuc2vtzvvxiop5zsvpnjb93p4nefofrpeqxpnk5dbus2zt9u++0vtuvyfelfwq1rt2u7j86ejyl5hrsz7/9+x80nt94637xdx8yu//+/d93jb+785sjvwdu/j+9nzc1fvv9p7a5v1frmdl8+nd4spru34zqklohwd0qktwhnpwdjf1ly/5ssl82ibuzjjyidl3pyfswdjwezb1mi7vazn8zwh+68l7wjdq04okszlurkrfuig7tjkgsersq1dsusqateq4o31kk9pjnrq/qmrijuvjmcrho5uyzqvkmmtioqjbqhlesjcm1x3qaaaltuleqvr4no2c2x/a2bwafrnibattyiiwmnusm46begyczdy7ctc47iztdkbjdj1u09ad9v9/qcqeskdlbrpx4pfvys9y+nzovefcbxpcb0hrlh+en9cnzg/lrn+fhieto+nuo9pmlqzkbezpyqhrrzz1zporwm4ddwuilauakhpfb5uiuzyicblsbfsodlm/kysgwv6izihta3l4kkip1670khljvqwjyvooqm2biak1j7f3lb81nbkkap6rnalzpo5vrpbp2okqq3nbowpyiz6kvqa23fkx1dmlwak2jgozovtrkpmt1k5rjguyqk5ugsi3z1h7wrxoza1xqglgflqk8zq975ip3rpn6dkda+r5esfr54vsymd4mjcjtrmmhs6tlc1pshfmpstqnta3vbmo2zloiuw5thch0lmzkqsu6+fhw46kigqhynlasxpmslubr8kd0ba77fboztvyi/oqhtoocx4ossqhlldldnympxyuei2rylhwrmnwi9orlkhpm9uipahqyzvzxojgjirhzx8wz80lspn8z30kxca3l4haj7dexym1k5vsmvg9ceoysm0vsao2yjkzrbfizjedjbxojkt1crgzojeq1cs3d1ypyt/tjddybb0dh3seo8d14qdhmnqn+bugktgb7hzzp45du0y0er2ytdseo3e+28njxcrovwdbvq8rt8pavq8st7mfrf6l9nwi5hrnewtbvh4mcbrs9r/ceuuh5aafmnpkktbjt+7ojnqtvr3e6h2d3xu7ykkgur8vgr65wacicjn/3pi8nijxzyyfsntohpxoiaw+uzhfbtjvwhkr0iyf3b8grhdiyvapcqecujn+fhd8f4awhtfbxvkjgjkboiaotxtf/vwitrlhidtfuybwrhbu8l5rqjp6zcy+tjq7iefl9bbh2slp6hftrowus6h2jvx25gkv6ehxpazsfaqybwotgit9iothtdwkrmdt/exzz6xk9e4wrh+h4/9yfplc5pxk6bsuoxjn/z0lf40e10vuziq2wbsbzfoooai99m6f6hevzx71r6dh5rfrgygsvx3wi0dvhle2rheehgw/rasf8ryjil5kvvwira/l+subezl58hw8odxh/d6afjzjpz58fqgrv2h93qb8y/gz/byqhimjhsct9fjqozqyscdxr2w/mbxv2qzfgpxpumt+brzcscn6pcf5fedwe/jrieetgwxd4mum5rt8fkbpjtfx2ejx6rmcb78jc6gqmmpg8oogtufyjuy6rn8zhk839qzb7wmfkzt4ubdb4qvlutke364e5fxgw8/goz/bzgwnv3og56iqpoy0wmsfwa8vvay1jm2d/ulp4beofb+wfmm43gxoetxcmpvvcpejkhwedbdyyp3cchzhvr1cubefmulvh0tm58hxs200m0kln2tp5cf47tphhysnpv/q4gk5kbqvwl8wjohdz5wjja7bqpixwpymhluezeb/9aksd4b+i4y7l5wtjrtao8vwu48stwo38vwb+qp+n7dwjopew/ilut/gpe0hjdzpdk/utg7e4/k9p0nt4ott6okvofwyehrc4/09gqrpv08e6f4cfjomv/2nywd+bqwx+tgzfnuxkz+o6exgdul89q/tbwj2z8v4yepr80svj5j3unplj4nxe2y/elt7xiqps/przm8r+4fq5sgdwf0o+j2yhxi4t7qj9vrcz285gfpt7xr74epr89tl2w+e0uulkun3co3ghz19uoyf3wldll/muwt5lqogvpucxx4o+r1b8ps8qx6lag+1esfurin67z/uun+igxkn5ffqg98hvw9+bp12fx7zdb+dre/lbe7o9mench5j6q9tp7rbs9t7z51d39rrb7jt+qpss1va6z/w01vllzh7s6v1o9z+ihydq8/p3n+bov5lzv7u3on9wmc7g1skzn9+b99+4i6er6z2d3f1fozx0g9glznnm+sd3b+gbbnypr3cxuigc2bs7hes2hfa90oon99c3u/j/i4hfsvzd7gvfpb3pkzfeh8zkmh1iyhsun/g1t6w39xjr8ha2k3kawdxwpn9i8/zuhxld4c0hn/v+moge4yrmyyqk703eh6r6xmcaiewzf7z0up1mso/k4gbuj4+ae+xw7m5ymri7xjcb3x6bggwhm/+aawho8og8hbm+d13fjj0ak5y00iampe7rzxewgdg9ocfesdsavgczvg9c300oh7o3gqxwgui8k02x2ycwuxs9q/8juqmvh9mejq7f5oapyps6sctpqp6fjcz53rxt8c/qmt/4mxhoabcfpfn4effotkti4fgklif1lrj5hrj096xqm122gdptlfv7qlmel5uftxzk8nrsmxdeyp5bbm+d/wz8ehq39xkkkfvoszpz/nps/x/ndwti1eg0iycmlv9vbxrzgmabuamnah05tbnuohbra4w7mowrzbfu5bamwzj55me7nswobljeqg+hdyt8vwl60xszjvti0rnjqhv2n3s09gj+bqsnoi05phryoh5pie3ngg82umadb1f7wc3dzq+wbwb9f/5alowb8hid9oewmwn85t/bswmgyi3bdsibegwrxvojetnxmzcwhyggs9g+k6t1fdytnkbmzs2uy5byklzz392mrljkh68htlaal7pd3yxuvgr/iw6ge2hh05oj5wtiypaahljiqjvu4kpnk/vsmryrppj+sl5zvsrgp5vcbcp6qic6pxsjj68rdkityf81igyhy/pjff0p2kkvzdwcdwyxzbxr6rcep0yzejthyw+iym6nxfcmqnw9jek5aqih8f1ewveap3ht9laqnx5vymfeotxixb5jeqghmv3my+al3d7d3jb4nq3bgokszduaxox7i9u+897+789ybx1n/n5m8bk0iuh2jgct9v18ug//rno8csg83qxx8tq01bxqzviosn0uuvb0u2/yhluz1vcgyfuak23u6dv8dydvxl1+696+2+ioz3+677tp5eqnbxv0ewm9gn98byoe6fm7x+bcwvibviboyc6fhv1ohr3fsshtxf1ikk+ctbnjcbcatq52bdssx11vr2mqupzrn+v1wr9fn82vq/op2rruav7s97+dnspbrxih9fhxkj4suqgpufpyfwulrysbglmollt5j7mecsbfn7mqgancx6riez4odghnztx8perdcsuj2/cdbza3yyjhmbmjr19xasc8tkgb0n/j1+oigy+bdinkffuf/bjuztbt6aal0hvzga4rfzghllwiotnoqbb9pkxj5wguerdcchi3ljiekmqwzvnjhvvmwzefpkxjzegusgcoer8fscocdqbgetk4cjmkbpuzravmsekxmus4w9/so7ksenfbhy1fltgm7n/ivzxt4hxhestvs+x6jneq5phze1rknrgejdozxyur+kzgf0g6krxz+mmpgveca6ltebxgisshtw9zhecbqee0wunkxr7hfwjvde3ypujuusxopnoo/o0/dgdlyg7aazi56vnyzyh1hla99mhi4/duoiror5o6qi/pdxx69mart3otfkkhjqd76qpq0vkssovq7s/jwdxq2uysusufuftg0udq6k4qrgymzfigoe4ngixfuepm7zxi6qhulplbmcxhpafijlk37p2wlorsiqvjv2dm/ikfsbb96uq0yvtmbmpm4jzhhsomhec7musrfyzjxt0mep6ctcox5qsqo1+gobobi6vzmkzltsma+prfot2lwvmqbwnvycbepfi2b9xb7x5g0vy9lsubbndwaa6zvmpgygwrm3g1dfgkqnforrc+jm3rtzvepkriayhnzc1i5sdsmlk/whcjdwqyatpyaaaaabjru5erkjggg=='} alt=""/> 164 \</div> 165 )} 166 buttontext="login" 167 onsuccess={handlegoogleloginloginresponse} 168 onfailure={handlegoogleloginloginresponse} 169 cookiepolicy={'single host origin'} 170 /> 171 \<div classname="login social item"> 172 \<img classname="login social item image" src={'data\ image/png;base64,ivborw0kggoaaaansuheugaaaoeaaadhcamaaaajbsjiaaaav1bmvewzmzn///+skpkvlzwrkzh19fwgokdg4ocampqjo6p8/py+vr7l5ex29vb5+fniymirq6vq0ndp6enw1ta3t7fu1ns7u7uwsldkysrv7+/b29vi4uktra2ojcyuaaajguleqvr4no2d6zrqiaygkdsldrsrvh3v/zppq6pjjculxhlnod9/av8lauistkjsq8oxaetzfgjkclqhrboojxxoglcvae0dyz33doyitxdoubnhnrvhdysfqjoacfd7c4f39whxhfvj99cig/obryesbbpwqjjl7apfn7kl1rifmfavziebchzq2fqgdqwe9cgi/ckcctqfn/cyevh6sbqfnxapajysd4hnwacalpd4qmtc3gnjlsnqwprgjiwgqjnkgjq4hbxqrxvnrr4sk/atbpqzhjejd2ax7yfhh8hjihloyudjzb4tjzd3rwrko2k8wgu8chtlkreoteirrha+yzkhj8uibje+amwj9krihb9yh5vzdq+krijzurkhxllxclfivnhrjfwsoityijqbhzeik5rqzkl6vhrctiukogiud5nriix0flpw8gkxcffdkmdmkiieh9gntd8lhxebcdfrkvtleqixliq1il0+try5gj6rturwss+bnhdzf0pofgdnt7geavmrd+k9jiecwq5esqx3tzmthihcfwbot1gaw/avgnmtdocrer+dgyynzpye0lb0oskjfz3uzzvxphbqwpxhqzpkltxundxhbjtqgdhf9g9pihsv+4cjbkkxtilnhd5ntbj5rejs7vdaj05us9mfny+rxmrbvzu54rebc9acqhd/vssdj3jgd+3mvcq2agpjzwyg2nemr9d/qprwh89j0xwxn/xsactxwgyltpzp+53ymju1exu8pnxm04shbv4uba/befibumwzn6ewpk5kc27p29worbp5uw02sk8rbo6tsw+xy/1bwddv3j3cotpz612xu9s0x6bv+qthsxpenxqm8mvox2weijnq1rvf1wysx0mjz4vbzwd7v9prxmm2n6foadt1byu4zsywwtko/cevr2qkzaqds2jb1xz3pmyqwg2v7/jkabb1dqbdjnefr8acmyadccvwf355p24x0tcqkym986e9hsuktvjp2x/6on7u/aptc/l8381lzfpnjczxmbgp+nlt11x3gr3tdpt8n6xufboe4tp76rwgduv2qooonxpwwalrikx48fx7myftopvbpj7kiurceqdxsoljyrcgd8gxitiy6yrduov7nsyoscbsxeapqhbekqfsqaiikxcnsytehjkbgigc+rfz6dikkeny6loi93kgz5xcenanietgeahxcpsealmomggbuk0zvclbysc4yapzypwftxgoirz/okbudrtjumiyngeiu0mameiwweeb8o0fqrhsbmucvkveckeijg0i+pphqt1mxs0pfgyyem2/iiosiew4hvyirxpaitjiqpstep37ekhquwipb4oqowzdso/uhagvf0jgtgza2cj+hiycdibq8yo0zzzq+wkv7+xztfj8hirtdcv/0k+i59dfusoqmoelxopyrfthafqt7tv2uvjcjxcqtatcffof4uztj+xmfbchxu/fiqfojcsqx0qto3xir6h3rmac+gjxwjsppw3aq4gl60ytp4nwq6h3nuqc+gi1+i8c5ueme2o1ni6fhokh1lpzcqjzok6odtm9zan6cbdacxnbcoaqlwiuryelzmcjte7vawynh1drzbfsngocuovmma2oezjoqhu6taezfeoewinoaialcuk8mgukhzrxgyvckzu0corqj9x+e/4nvokvlbzfjdak0+69cmvmfl2eafno72vpxfbeagnfdk9q1zrio2c161itujx23p7gbveqymp/r/1hsonpcukgbfxcwtgdie4ilp6lqwbtm06o9nw0oatvokheoyf+dunjhhqd9vh3jowtoiw344ndtccjfqd4sxffnh2x2l7kp8j3ekqdepl7rn8pd2wov7gxpb9dpilh3pzgivr7rgry6xopodo98cdlqmrm817fpodei7/0ez5iy0bihuh7clwec1/e8qz7cdwbgl5oli9wrxfdnohxsytxt67wkxerxaudrijddxnbzj+ul/connbr4729hkrn/ehuwfeds4k+hfztwaj1eqouoih6cxxpigdzskf1e2ovgdhilfhocjg3vr00/zkbo/miqlh9g49iykebcbu73o6fxf8brtcodkfdcykybbgqdtbccywubrgqdcl4kfv6rymyg/mm3xsqlx1hgidh23ttqwk5xv/9jevtpgjcgw5himmnab+v50qdjtr7jjgitwo0tpgoa9obpcelsdyjdl/gnzynnh1cwl+prfhvv8riutxv9k/ynpxihfqz2b7klbwaeb6nrffmjqkr0/rdnwdz74u2kkhiykr38jui8eh3ttfu97l+mqy4oelootv535+qwfageygoponaqlduzu0weh1kfor6wr+mzqaqbrv/rda2mprjfjsaerzqriju/hftml6glg2mnfp5lcrakuaoura+g0okibl9is0pfuzgjfr8mih8qvjdqwq9bmi4kzvq7xyde3nyzq3scifapojlunfjiccn0lojk43ghhchycj/vrilcos6uqxchb5tsjoij4dfnqocljjaivr3trupvjhvh2ghq5+mpfu6ezumve2kxobehqgqfuoe7ih5lcj7sk165tzduzolqe4ryvd80tlvl6n5xwxcjtuz0pfdpj4knxqgiuee4hdczb9/ce5k+uugvf6kf6kl5rl4ljc6taepwldctdyjp2vvhqgijjtuynn56mgesr0pkblrfsbmpmlngy5bnikumnbdao54j6aayatniu1wrxncpj6ej3yvpxhhmltyp35nbwrkrmtp2tjnlfvnaybpeszjyxhhz+fdfnexfbb+qdrdobtcs3qecjocnhiddv0zmqfu7zmqjjyc49gthmnroe/n7dkhfeazkksjkce1ewc9s5iss3dacnbscm/7ovgix9kwaexyz3qameka4305z1tqcbnpfmb0vhbnggqik1u++nlolg1nel415tikc0va7dmrjaj7rpq7x33vpvnfvzfltu3sl8resowhhfqsgcjex1p/lu7yl1vtbeb9qd6fjo05b1k7z1nxoy5ijldvzfu2b09lvzqb1x5/alyvmmpfht+c/6dv/qmh/ovcu90claaaaabjru5erkjggg=='} alt=""/> 173 \</div> 174 \</div> 175 \<p classname="form hint">don't have an account? \<a classname="form link" href="#">sign up\</a>\</p> 176 \</div> 177 )} 178 {currentuser !== null && ( 179 \<div classname="container"> 180 \<h2 classname="heading">{'user screen'}\</h2> 181 \<divider /> 182 \<h2 classname="heading">{`hello ${currentuser get('username')}!`}\</h2> 183 \<div classname="form buttons"> 184 \<button 185 onclick={() => douserlogout()} 186 type="primary" 187 classname="form button" 188 color={'#208aec'} 189 size="large" 190 block 191 > 192 log out 193 \</button> 194 \</div> 195 \</div> 196 )} 197 \</div> 198 ); 199 };1 import react, { usestate, fc, reactelement } from 'react'; 2 import ' /app css'; 3 import { button, divider, input } from 'antd'; 4 import googlelogin from 'react google login'; 5 const parse = require('parse/dist/parse min js'); 6	 7 export const userlogin fc<{}> = () reactelement => { 8 // state variables 9 const \[username, setusername] = usestate(''); 10 const \[password, setpassword] = usestate(''); 11 const \[currentuser, setcurrentuser] = usestate\<parse object | null>(null); 12	 13 const douserlogin = async function () promise\<boolean> { 14 // note that these values come from state variables that we've declared before 15 const usernamevalue string = username; 16 const passwordvalue string = password; 17 try { 18 const loggedinuser parse user = await parse user login(usernamevalue, passwordvalue); 19 // login returns the corresponding parseuser object 20 alert( 21 `success! user ${loggedinuser get('username')} has successfully signed in!`, 22 ); 23 // to verify that this is in fact the current user, `current` can be used 24 const currentuser parse user = await parse user current(); 25 console log(loggedinuser === currentuser); 26 // clear input fields 27 setusername(''); 28 setpassword(''); 29 // update state variable holding current user 30 getcurrentuser(); 31 return true; 32 } catch (error any) { 33 // error can be caused by wrong parameters or lack of internet connection 34 alert(`error! ${error message}`); 35 return false; 36 } 37 }; 38	 39 const douserlogout = async function () promise\<boolean> { 40 try { 41 await parse user logout(); 42 // to verify that current user is now empty, currentasync can be used 43 const currentuser parse user = await parse user current(); 44 if (currentuser === null) { 45 alert('success! no user is logged in anymore!'); 46 } 47 // update state variable holding current user 48 getcurrentuser(); 49 return true; 50 } catch (error any) { 51 alert(`error! ${error message}`); 52 return false; 53 } 54 }; 55	 56 // function that will return current user and also update current username 57 const getcurrentuser = async function () promise\<parse user | null> { 58 const currentuser (parse user | null) = await parse user current(); 59 // update state variable holding current user 60 setcurrentuser(currentuser); 61 return currentuser; 62 } 63	 64 const handlegoogleloginloginresponse = async function(response any) promise\<boolean> { 65 // check if response has an error 66 if (response error !== undefined) { 67 console log(`error ${response error}`); 68 return false; 69 } else { 70 try { 71 // gather google user info 72 const usergoogleid string = response googleid; 73 const usertokenid string = response tokenid; 74 const useremail string = response profileobj email; 75 // try to login on parse using linkwith and these credentials 76 // create a new parse user object 77 const usertologin parse user = new parse user(); 78 // set username and email to match google email 79 usertologin set('username', useremail); 80 usertologin set('email', useremail); 81 try { 82 let loggedinuser parse user = await usertologin 83 linkwith('google', { 84 authdata {id usergoogleid, id token usertokenid}, 85 }); 86 // login returns the corresponding parseuser object 87 alert( 88 `success! user ${loggedinuser get('username')} has successfully signed in!`, 89 ); 90 // update state variable holding current user 91 getcurrentuser(); 92 return true; 93 } catch (error any) { 94 // error can be caused by wrong parameters or lack of internet connection 95 alert(`error! ${error message}`); 96 return false; 97 } 98 } catch (error any) { 99 console log("error gathering google user info, please try again!") 100 return false; 101 } 102 } 103 } 104	 105 return ( 106 \<div> 107 \<div classname="header"> 108 \<img 109 classname="header logo" 110 alt="back4app logo" 111 src={ 112 'https //blog back4app com/wp content/uploads/2019/05/back4app white logo 500px png' 113 } 114 /> 115 \<p classname="header text bold">{'react on back4app'}\</p> 116 \<p classname="header text">{'user login'}\</p> 117 \</div> 118 {currentuser === null && ( 119 \<div classname="container"> 120 \<h2 classname="heading">{'user login'}\</h2> 121 \<divider /> 122 \<div classname="form wrapper"> 123 \<input 124 value={username} 125 onchange={(event) => setusername(event target value)} 126 placeholder="username" 127 size="large" 128 classname="form input" 129 /> 130 \<input 131 value={password} 132 onchange={(event) => setpassword(event target value)} 133 placeholder="password" 134 size="large" 135 type="password" 136 classname="form input" 137 /> 138 \</div> 139 \<div classname="form buttons"> 140 \<button 141 onclick={() => douserlogin()} 142 type="primary" 143 classname="form button" 144 color={'#208aec'} 145 size="large" 146 block 147 > 148 log in 149 \</button> 150 \</div> 151 \<divider /> 152 \<div classname="login social"> 153 \<div classname="login social item login social item facebook"> 154 \<img classname="login social item image" src={'https //findicons com/files/icons/2830/clean social icons/250/facebook png'} alt=""/> 155 \</div> 156 \<googlelogin 157 clientid="108490793456 0flm4qh8ek4cb4krt7e06980o4sjvado apps googleusercontent com" 158 render={renderprops => ( 159 \<div classname="login social item"> 160 \<img onclick={renderprops onclick} classname="login social item image" src={'data\ image/png;base64,ivborw0kggoaaaansuheugaaan8aaadicamaaad5w+jtaaabwvbmvex////qqzu0qfnchft7vauufppk7f08gvr0o/zzofb7uqd7uadpncp/vqdqpzaspk7plhrpoysyoklpoyzpnst97ovwgnskpensxfh8wgavouhplrj+9/b0pad4xsoix5fd7+h74udvenlru0f61tt1r6vuc2vtzvvxiop5zsvpnjb93p4nefofrpeqxpnk5dbus2zt9u++0vtuvyfelfwq1rt2u7j86ejyl5hrsz7/9+x80nt94637xdx8yu//+/d93jb+785sjvwdu/j+9nzc1fvv9p7a5v1frmdl8+nd4spru34zqklohwd0qktwhnpwdjf1ly/5ssl82ibuzjjyidl3pyfswdjwezb1mi7vazn8zwh+68l7wjdq04okszlurkrfuig7tjkgsersq1dsusqateq4o31kk9pjnrq/qmrijuvjmcrho5uyzqvkmmtioqjbqhlesjcm1x3qaaaltuleqvr4no2c2x/a2bwafrnibattyiiwmnusm46begyczdy7ctc47iztdkbjdj1u09ad9v9/qcqeskdlbrpx4pfvys9y+nzovefcbxpcb0hrlh+en9cnzg/lrn+fhieto+nuo9pmlqzkbezpyqhrrzz1zporwm4ddwuilauakhpfb5uiuzyicblsbfsodlm/kysgwv6izihta3l4kkip1670khljvqwjyvooqm2biak1j7f3lb81nbkkap6rnalzpo5vrpbp2okqq3nbowpyiz6kvqa23fkx1dmlwak2jgozovtrkpmt1k5rjguyqk5ugsi3z1h7wrxoza1xqglgflqk8zq975ip3rpn6dkda+r5esfr54vsymd4mjcjtrmmhs6tlc1pshfmpstqnta3vbmo2zloiuw5thch0lmzkqsu6+fhw46kigqhynlasxpmslubr8kd0ba77fboztvyi/oqhtoocx4ossqhlldldnympxyuei2rylhwrmnwi9orlkhpm9uipahqyzvzxojgjirhzx8wz80lspn8z30kxca3l4haj7dexym1k5vsmvg9ceoysm0vsao2yjkzrbfizjedjbxojkt1crgzojeq1cs3d1ypyt/tjddybb0dh3seo8d14qdhmnqn+bugktgb7hzzp45du0y0er2ytdseo3e+28njxcrovwdbvq8rt8pavq8st7mfrf6l9nwi5hrnewtbvh4mcbrs9r/ceuuh5aafmnpkktbjt+7ojnqtvr3e6h2d3xu7ykkgur8vgr65wacicjn/3pi8nijxzyyfsntohpxoiaw+uzhfbtjvwhkr0iyf3b8grhdiyvapcqecujn+fhd8f4awhtfbxvkjgjkboiaotxtf/vwitrlhidtfuybwrhbu8l5rqjp6zcy+tjq7iefl9bbh2slp6hftrowus6h2jvx25gkv6ehxpazsfaqybwotgit9iothtdwkrmdt/exzz6xk9e4wrh+h4/9yfplc5pxk6bsuoxjn/z0lf40e10vuziq2wbsbzfoooai99m6f6hevzx71r6dh5rfrgygsvx3wi0dvhle2rheehgw/rasf8ryjil5kvvwira/l+subezl58hw8odxh/d6afjzjpz58fqgrv2h93qb8y/gz/byqhimjhsct9fjqozqyscdxr2w/mbxv2qzfgpxpumt+brzcscn6pcf5fedwe/jrieetgwxd4mum5rt8fkbpjtfx2ejx6rmcb78jc6gqmmpg8oogtufyjuy6rn8zhk839qzb7wmfkzt4ubdb4qvlutke364e5fxgw8/goz/bzgwnv3og56iqpoy0wmsfwa8vvay1jm2d/ulp4beofb+wfmm43gxoetxcmpvvcpejkhwedbdyyp3cchzhvr1cubefmulvh0tm58hxs200m0kln2tp5cf47tphhysnpv/q4gk5kbqvwl8wjohdz5wjja7bqpixwpymhluezeb/9aksd4b+i4y7l5wtjrtao8vwu48stwo38vwb+qp+n7dwjopew/ilut/gpe0hjdzpdk/utg7e4/k9p0nt4ott6okvofwyehrc4/09gqrpv08e6f4cfjomv/2nywd+bqwx+tgzfnuxkz+o6exgdul89q/tbwj2z8v4yepr80svj5j3unplj4nxe2y/elt7xiqps/przm8r+4fq5sgdwf0o+j2yhxi4t7qj9vrcz285gfpt7xr74epr89tl2w+e0uulkun3co3ghz19uoyf3wldll/muwt5lqogvpucxx4o+r1b8ps8qx6lag+1esfurin67z/uun+igxkn5ffqg98hvw9+bp12fx7zdb+dre/lbe7o9mench5j6q9tp7rbs9t7z51d39rrb7jt+qpss1va6z/w01vllzh7s6v1o9z+ihydq8/p3n+bov5lzv7u3on9wmc7g1skzn9+b99+4i6er6z2d3f1fozx0g9glznnm+sd3b+gbbnypr3cxuigc2bs7hes2hfa90oon99c3u/j/i4hfsvzd7gvfpb3pkzfeh8zkmh1iyhsun/g1t6w39xjr8ha2k3kawdxwpn9i8/zuhxld4c0hn/v+moge4yrmyyqk703eh6r6xmcaiewzf7z0up1mso/k4gbuj4+ae+xw7m5ymri7xjcb3x6bggwhm/+aawho8og8hbm+d13fjj0ak5y00iampe7rzxewgdg9ocfesdsavgczvg9c300oh7o3gqxwgui8k02x2ycwuxs9q/8juqmvh9mejq7f5oapyps6sctpqp6fjcz53rxt8c/qmt/4mxhoabcfpfn4effotkti4fgklif1lrj5hrj096xqm122gdptlfv7qlmel5uftxzk8nrsmxdeyp5bbm+d/wz8ehq39xkkkfvoszpz/nps/x/ndwti1eg0iycmlv9vbxrzgmabuamnah05tbnuohbra4w7mowrzbfu5bamwzj55me7nswobljeqg+hdyt8vwl60xszjvti0rnjqhv2n3s09gj+bqsnoi05phryoh5pie3ngg82umadb1f7wc3dzq+wbwb9f/5alowb8hid9oewmwn85t/bswmgyi3bdsibegwrxvojetnxmzcwhyggs9g+k6t1fdytnkbmzs2uy5byklzz392mrljkh68htlaal7pd3yxuvgr/iw6ge2hh05oj5wtiypaahljiqjvu4kpnk/vsmryrppj+sl5zvsrgp5vcbcp6qic6pxsjj68rdkityf81igyhy/pjff0p2kkvzdwcdwyxzbxr6rcep0yzejthyw+iym6nxfcmqnw9jek5aqih8f1ewveap3ht9laqnx5vymfeotxixb5jeqghmv3my+al3d7d3jb4nq3bgokszduaxox7i9u+897+789ybx1n/n5m8bk0iuh2jgct9v18ug//rno8csg83qxx8tq01bxqzviosn0uuvb0u2/yhluz1vcgyfuak23u6dv8dydvxl1+696+2+ioz3+677tp5eqnbxv0ewm9gn98byoe6fm7x+bcwvibviboyc6fhv1ohr3fsshtxf1ikk+ctbnjcbcatq52bdssx11vr2mqupzrn+v1wr9fn82vq/op2rruav7s97+dnspbrxih9fhxkj4suqgpufpyfwulrysbglmollt5j7mecsbfn7mqgancx6riez4odghnztx8perdcsuj2/cdbza3yyjhmbmjr19xasc8tkgb0n/j1+oigy+bdinkffuf/bjuztbt6aal0hvzga4rfzghllwiotnoqbb9pkxj5wguerdcchi3ljiekmqwzvnjhvvmwzefpkxjzegusgcoer8fscocdqbgetk4cjmkbpuzravmsekxmus4w9/so7ksenfbhy1fltgm7n/ivzxt4hxhestvs+x6jneq5phze1rknrgejdozxyur+kzgf0g6krxz+mmpgveca6ltebxgisshtw9zhecbqee0wunkxr7hfwjvde3ypujuusxopnoo/o0/dgdlyg7aazi56vnyzyh1hla99mhi4/duoiror5o6qi/pdxx69mart3otfkkhjqd76qpq0vkssovq7s/jwdxq2uysusufuftg0udq6k4qrgymzfigoe4ngixfuepm7zxi6qhulplbmcxhpafijlk37p2wlorsiqvjv2dm/ikfsbb96uq0yvtmbmpm4jzhhsomhec7musrfyzjxt0mep6ctcox5qsqo1+gobobi6vzmkzltsma+prfot2lwvmqbwnvycbepfi2b9xb7x5g0vy9lsubbndwaa6zvmpgygwrm3g1dfgkqnforrc+jm3rtzvepkriayhnzc1i5sdsmlk/whcjdwqyatpyaaaaabjru5erkjggg=='} alt=""/> 161 \</div> 162 )} 163 buttontext="login" 164 onsuccess={handlegoogleloginloginresponse} 165 onfailure={handlegoogleloginloginresponse} 166 cookiepolicy={'single host origin'} 167 /> 168 \<div classname="login social item"> 169 \<img classname="login social item image" src={'data\ image/png;base64,ivborw0kggoaaaansuheugaaaoeaaadhcamaaaajbsjiaaaav1bmvewzmzn///+skpkvlzwrkzh19fwgokdg4ocampqjo6p8/py+vr7l5ex29vb5+fniymirq6vq0ndp6enw1ta3t7fu1ns7u7uwsldkysrv7+/b29vi4uktra2ojcyuaaajguleqvr4no2d6zrqiaygkdsldrsrvh3v/zppq6pjjculxhlnod9/av8lauistkjsq8oxaetzfgjkclqhrboojxxoglcvae0dyz33doyitxdoubnhnrvhdysfqjoacfd7c4f39whxhfvj99cig/obryesbbpwqjjl7apfn7kl1rifmfavziebchzq2fqgdqwe9cgi/ckcctqfn/cyevh6sbqfnxapajysd4hnwacalpd4qmtc3gnjlsnqwprgjiwgqjnkgjq4hbxqrxvnrr4sk/atbpqzhjejd2ax7yfhh8hjihloyudjzb4tjzd3rwrko2k8wgu8chtlkreoteirrha+yzkhj8uibje+amwj9krihb9yh5vzdq+krijzurkhxllxclfivnhrjfwsoityijqbhzeik5rqzkl6vhrctiukogiud5nriix0flpw8gkxcffdkmdmkiieh9gntd8lhxebcdfrkvtleqixliq1il0+try5gj6rturwss+bnhdzf0pofgdnt7geavmrd+k9jiecwq5esqx3tzmthihcfwbot1gaw/avgnmtdocrer+dgyynzpye0lb0oskjfz3uzzvxphbqwpxhqzpkltxundxhbjtqgdhf9g9pihsv+4cjbkkxtilnhd5ntbj5rejs7vdaj05us9mfny+rxmrbvzu54rebc9acqhd/vssdj3jgd+3mvcq2agpjzwyg2nemr9d/qprwh89j0xwxn/xsactxwgyltpzp+53ymju1exu8pnxm04shbv4uba/befibumwzn6ewpk5kc27p29worbp5uw02sk8rbo6tsw+xy/1bwddv3j3cotpz612xu9s0x6bv+qthsxpenxqm8mvox2weijnq1rvf1wysx0mjz4vbzwd7v9prxmm2n6foadt1byu4zsywwtko/cevr2qkzaqds2jb1xz3pmyqwg2v7/jkabb1dqbdjnefr8acmyadccvwf355p24x0tcqkym986e9hsuktvjp2x/6on7u/aptc/l8381lzfpnjczxmbgp+nlt11x3gr3tdpt8n6xufboe4tp76rwgduv2qooonxpwwalrikx48fx7myftopvbpj7kiurceqdxsoljyrcgd8gxitiy6yrduov7nsyoscbsxeapqhbekqfsqaiikxcnsytehjkbgigc+rfz6dikkeny6loi93kgz5xcenanietgeahxcpsealmomggbuk0zvclbysc4yapzypwftxgoirz/okbudrtjumiyngeiu0mameiwweeb8o0fqrhsbmucvkveckeijg0i+pphqt1mxs0pfgyyem2/iiosiew4hvyirxpaitjiqpstep37ekhquwipb4oqowzdso/uhagvf0jgtgza2cj+hiycdibq8yo0zzzq+wkv7+xztfj8hirtdcv/0k+i59dfusoqmoelxopyrfthafqt7tv2uvjcjxcqtatcffof4uztj+xmfbchxu/fiqfojcsqx0qto3xir6h3rmac+gjxwjsppw3aq4gl60ytp4nwq6h3nuqc+gi1+i8c5ueme2o1ni6fhokh1lpzcqjzok6odtm9zan6cbdacxnbcoaqlwiuryelzmcjte7vawynh1drzbfsngocuovmma2oezjoqhu6taezfeoewinoaialcuk8mgukhzrxgyvckzu0corqj9x+e/4nvokvlbzfjdak0+69cmvmfl2eafno72vpxfbeagnfdk9q1zrio2c161itujx23p7gbveqymp/r/1hsonpcukgbfxcwtgdie4ilp6lqwbtm06o9nw0oatvokheoyf+dunjhhqd9vh3jowtoiw344ndtccjfqd4sxffnh2x2l7kp8j3ekqdepl7rn8pd2wov7gxpb9dpilh3pzgivr7rgry6xopodo98cdlqmrm817fpodei7/0ez5iy0bihuh7clwec1/e8qz7cdwbgl5oli9wrxfdnohxsytxt67wkxerxaudrijddxnbzj+ul/connbr4729hkrn/ehuwfeds4k+hfztwaj1eqouoih6cxxpigdzskf1e2ovgdhilfhocjg3vr00/zkbo/miqlh9g49iykebcbu73o6fxf8brtcodkfdcykybbgqdtbccywubrgqdcl4kfv6rymyg/mm3xsqlx1hgidh23ttqwk5xv/9jevtpgjcgw5himmnab+v50qdjtr7jjgitwo0tpgoa9obpcelsdyjdl/gnzynnh1cwl+prfhvv8riutxv9k/ynpxihfqz2b7klbwaeb6nrffmjqkr0/rdnwdz74u2kkhiykr38jui8eh3ttfu97l+mqy4oelootv535+qwfageygoponaqlduzu0weh1kfor6wr+mzqaqbrv/rda2mprjfjsaerzqriju/hftml6glg2mnfp5lcrakuaoura+g0okibl9is0pfuzgjfr8mih8qvjdqwq9bmi4kzvq7xyde3nyzq3scifapojlunfjiccn0lojk43ghhchycj/vrilcos6uqxchb5tsjoij4dfnqocljjaivr3trupvjhvh2ghq5+mpfu6ezumve2kxobehqgqfuoe7ih5lcj7sk165tzduzolqe4ryvd80tlvl6n5xwxcjtuz0pfdpj4knxqgiuee4hdczb9/ce5k+uugvf6kf6kl5rl4ljc6taepwldctdyjp2vvhqgijjtuynn56mgesr0pkblrfsbmpmlngy5bnikumnbdao54j6aayatniu1wrxncpj6ej3yvpxhhmltyp35nbwrkrmtp2tjnlfvnaybpeszjyxhhz+fdfnexfbb+qdrdobtcs3qecjocnhiddv0zmqfu7zmqjjyc49gthmnroe/n7dkhfeazkksjkce1ewc9s5iss3dacnbscm/7ovgix9kwaexyz3qameka4305z1tqcbnpfmb0vhbnggqik1u++nlolg1nel415tikc0va7dmrjaj7rpq7x33vpvnfvzfltu3sl8resowhhfqsgcjex1p/lu7yl1vtbeb9qd6fjo05b1k7z1nxoy5ijldvzfu2b09lvzqb1x5/alyvmmpfht+c/6dv/qmh/ovcu90claaaaabjru5erkjggg=='} alt=""/> 170 \</div> 171 \</div> 172 \<p classname="form hint">don't have an account? \<a classname="form link" href="#">sign up\</a>\</p> 173 \</div> 174 )} 175 {currentuser !== null && ( 176 \<div classname="container"> 177 \<h2 classname="heading">{'user screen'}\</h2> 178 \<divider /> 179 \<h2 classname="heading">{`hello ${currentuser get('username')}!`}\</h2> 180 \<div classname="form buttons"> 181 \<button 182 onclick={() => douserlogout()} 183 type="primary" 184 classname="form button" 185 color={'#208aec'} 186 size="large" 187 block 188 > 189 log out 190 \</button> 191 \</div> 192 \</div> 193 )} 194 \</div> 195 ); 196 }; добавьте эти классы в ваш app css app css файл, если вы хотите полностью отобразить макет этого компонента app css 1 @import ' antd/dist/antd css'; 2	 3 app { 4 text align center; 5 } 6	 7 html { 8 box sizing border box; 9 outline none; 10 overflow auto; 11 } 12	 13 , 14 before, 15 after { 16 margin 0; 17 padding 0; 18 box sizing inherit; 19 } 20	 21 h1, 22 h2, 23 h3, 24 h4, 25 h5, 26 h6 { 27 margin 0; 28 font weight bold; 29 } 30	 31 p { 32 margin 0; 33 } 34	 35 body { 36 margin 0; 37 background color #fff; 38 } 39	 40 container { 41 width 100%; 42 max width 900px; 43 margin auto; 44 padding 20px 0; 45 text align left; 46 } 47	 48 header { 49 align items center; 50 padding 25px 0; 51 background color #208aec; 52 } 53	 54 header logo { 55 height 55px; 56 margin bottom 20px; 57 object fit contain; 58 } 59	 60 header text bold { 61 margin bottom 3px; 62 color rgba(255, 255, 255, 0 9); 63 font size 16px; 64 font weight bold; 65 } 66	 67 header text { 68 color rgba(255, 255, 255, 0 9); 69 font size 15px; 70 } 71	 72 heading { 73 font size 22px; 74 } 75	 76 flex { 77 display flex; 78 } 79	 80 flex between { 81 display flex; 82 justify content space between; 83 } 84	 85 flex child { 86 flex 0 0 45%; 87 } 88	 89 heading button { 90 margin left 12px; 91 } 92	 93 list item { 94 padding bottom 15px; 95 margin bottom 15px; 96 border bottom 1px solid rgba(0, 0, 0, 0 06); 97 text align left; 98 } 99	 100 list item title { 101 color rgba(0, 0, 0, 0 87); 102 font size 17px; 103 } 104	 105 list item description { 106 color rgba(0, 0, 0, 0 5); 107 font size 15px; 108 } 109	 110 form input { 111 margin bottom 20px; 112 } 113	 114 login social { 115 display flex; 116 justify content center; 117 margin bottom 30px; 118 } 119	 120 login social item { 121 width 54px; 122 height 54px; 123 border radius 54px; 124 padding 12px; 125 margin 0 12px; 126 border 1px solid #e6e6e6; 127 box shadow 0 2px 4px #d6d6d6; 128 } 129	 130 login social item facebook { 131 padding 4px; 132 background color #3c5b9b; 133 } 134	 135 login social item image { 136 width 100%; 137 } 138	 139 form hint { 140 color rgba(0, 0, 0, 0 5); 141 font size 16px; 142 text align center; 143 } продолжайте и протестируйте вашу новую функцию если вам удалось войти в google и вызов linkwith linkwith был успешным, вы должны увидеть сообщение об успехе, подобное этому 3 проверка входа пользователя и создания сессии чтобы убедиться, что вход через google сработал, вы можете посмотреть на свою панель управления parse и увидеть вашего нового пользователя пользователя (если ваши данные аутентификации google не принадлежали другому пользователю), содержащего параметры authdata authdata вы также можете проверить, что действительная сессия была создана на панели управления, содержащей указатель на этот пользователь пользователь объект 4 связывание существующего пользователя с входом через google другим linkwith linkwith возможным использованием является связывание существующего пользователя с другим провайдером аутентификации, в данном случае, google добавьте эту функцию, которая вызывает linkwith linkwith так же, как и вход в ваш userlogin userlogin компонент единственное отличие здесь в том, что вместо вызова метода из пустого parse user parse user , вы будете использовать его из объекта текущего вошедшего пользователя javascript 1 const handlegoogleloginlinkresponse = async function(response) { 2 // check if response has an error 3 if (response error !== undefined) { 4 console log(`error ${response error}`); 5 return false; 6 } else { 7 try { 8 // gather google user info 9 const usergoogleid = response googleid; 10 const usertokenid = response tokenid; 11 // try to link current parse user using linkwith and these credentials 12 // get current user 13 const usertolink = await parse user current(); 14 try { 15 let loggedinuser = await usertolink 16 linkwith('google', { 17 authdata {id usergoogleid, id token usertokenid}, 18 }); 19 // login returns the corresponding parseuser object 20 alert( 21 `success! user ${loggedinuser get( 22 'username', 23 )} has successfully linked his google account!`, 24 ); 25 // update state variable holding current user 26 getcurrentuser(); 27 return true; 28 } catch (error) { 29 // error can be caused by wrong parameters or lack of internet connection 30 alert(`error! ${error message}`); 31 return false; 32 } 33 } catch (error) { 34 console log("error gathering google user info, please try again!") 35 return false; 36 } 37 } 38 }1 const handlegoogleloginlinkresponse = async function(response any) promise\<boolean> { 2 // check if response has an error 3 if (response error !== undefined) { 4 console log(`error ${response error}`); 5 return false; 6 } else { 7 try { 8 // gather google user info 9 const usergoogleid string = response googleid; 10 const usertokenid string = response tokenid; 11 // try to link current parse user using linkwith and these credentials 12 // get current user 13 const usertolink parse user = await parse user current(); 14 try { 15 let loggedinuser parse user = await usertolink 16 linkwith('google', { 17 authdata {id usergoogleid, id token usertokenid}, 18 }); 19 // login returns the corresponding parseuser object 20 alert( 21 `success! user ${loggedinuser get( 22 'username', 23 )} has successfully linked his google account!`, 24 ); 25 // update state variable holding current user 26 getcurrentuser(); 27 return true; 28 } catch (error any) { 29 // error can be caused by wrong parameters or lack of internet connection 30 alert(`error! ${error message}`); 31 return false; 32 } 33 } catch (error any) { 34 console log("error gathering google user info, please try again!") 35 return false; 36 } 37 } 38 } назначьте эту функцию на другой react google login react google login компонент на вашем главном экране, который отображается только когда в вашем приложении есть текущий пользователь протестируйте вашу новую функцию, отметив, что значение parse user parse user объекта authdata authdata будет обновлено с новыми данными провайдера аутентификации проверьте, действительно ли пользователь обновился в вашей панели управления parse сервером заключение в конце этого руководства вы узнали, как войти в систему, зарегистрироваться или связать существующих пользователей parse на react, используя вход через google с react google login react google login в следующем руководстве мы покажем вам, как использовать вход через apple