Kaip sukurti „TodoApp“ naudojant „ReactJS“ ir „Firebase“

Sveiki žmonės, sveiki atvykę į šią pamoką. Prieš pradėdami, turėtumėte būti susipažinę su pagrindinėmis „ReactJS“ sąvokomis. Jei ne, rekomenduočiau perskaityti ReactJS dokumentaciją.

Šioje programoje naudosime šiuos komponentus:

  1. ReactJS
  2. Materiali vartotojo sąsaja
  3. „Firebase“
  4. „ExpressJS“
  5. Paštininkas

Kaip atrodys mūsų programa:

Programos architektūra:

Mūsų komponentų supratimas:

Jums gali būti įdomu, kodėl šioje programoje naudojame „Firebase“. Na, jis teikia saugų autentifikavimą , realaus laiko duomenų bazę , komponentą be serverio ir saugyklos grupę .

Čia naudojame „Express“, kad mums nereikėtų tvarkyti HTTP išimčių. Mes naudosime visus „Firebase“ paketus savo funkcijų komponente. Taip yra todėl, kad nenorime, kad mūsų kliento programa būtų per didelė, o tai lėtina vartotojo sąsajos įkėlimo procesą.

Pastaba: Aš padalysiu šią pamoką į keturis atskirus skyrius. Kiekvieno skyriaus pradžioje rasite „git“ įsipareigojimą, kurio kodas yra sukurtas tame skyriuje. Taip pat, jei norite pamatyti visą kodą, jis yra prieinamas šioje saugykloje.

1 skyrius: „Todo“ API kūrimas

Šiameskyriuje , mes plėtosime šiuos elementus:

  1. Konfigūruokite „Firebase“ funkcijas.
  2. Įdiekite „Express“ struktūrą ir sukurkite „Todo“ API.
  3. „Firestore“ konfigūravimas kaip duomenų bazė.

Šiame skyriuje įdiegtą „ Todo“ API kodą galite rasti šiame įsipareigojime.

Konfigūruoti „Firebase“ funkcijas:

Eikite į „Firebase“ konsolę.

Pasirinkite parinktį Pridėti projektą . Po to sekite žemiau pateiktą gifą žingsnis po žingsnio, kad sukonfigūruotumėte „Firebase“ projektą.

Eikite į skirtuką funkcijos ir spustelėkite mygtuką Pradėti :

Pamatysite dialogo langą, kuriame yra instrukcijos, kaip nustatyti „Firebase“ funkcijas . Eikite į savo vietinę aplinką. Atidarykite komandinės eilutės įrankį. Norėdami įdiegti „Firebase“ įrankius į savo kompiuterį, naudokite toliau pateiktą komandą:

 npm install -g firebase-tools

Kai tai bus padaryta, naudokite komandą, firebase initkad sukonfigūruotumėte „Firebase“ funkcijas vietinėje aplinkoje. Inicijuodami „Firebase“ funkciją vietinėje aplinkoje, pasirinkite šias parinktis:

  1. Kurias „Firebase“ CLI funkcijas norite nustatyti šiam aplankui? Paspauskite tarpo klavišą, kad pasirinktumėte funkcijas, tada patvirtinkite „Enter“, kad patvirtintumėte savo pasirinkimą => Funkcijos: konfigūruokite ir įdiekite debesies funkcijas
  2. Pirmiausia susiekime šį projekto katalogą su „Firebase“ projektu…. => Naudokite esamą projektą
  3. Pasirinkite numatytąjį „Firebase“ projektą šiam katalogui => programos_pavadinimas
  4. Kokia kalba norėtumėte rašyti debesies funkcijas? => „ JavaScript“
  5. Ar norite naudoti „ESLint“, kad užfiksuotumėte galimas klaidas ir įtvirtintumėte stilių? => N
  6. Ar norite dabar įdiegti priklausomybes su npm? (Y / n) => Y

Baigę konfigūravimą gausite šį pranešimą:

✔ Firebase initialization complete!

Tai bus mūsų katalogų struktūra, kai bus baigta inicijavimas:

+-- firebase.json +-- functions | +-- index.js | +-- node_modules | +-- package-lock.json | +-- package.json

Dabar atidarykite index.jsfunkcijų katalogą ir nukopijuokite ir įklijuokite šį kodą:

const functions = require('firebase-functions'); exports.helloWorld = functions.https.onRequest((request, response) => { response.send("Hello from Firebase!"); });

Įdėkite kodą į „Firebase“ funkcijas naudodami šią komandą:

firebase deploy

Baigę diegimą, komandinės eilutės pabaigoje gausite šią prisijungimo liniją:

> ✔ Deploy complete! > Project Console: //console.firebase.google.com/project/todoapp-/overview

Eikite į „ Project Console> Functions“ ir ten rasite API URL. URL atrodys taip:

//-todoapp-.cloudfunctions.net/helloWorld

Nukopijuokite šį URL ir įklijuokite jį naršyklėje. Gausite tokį atsakymą:

Hello from Firebase!

Tai patvirtina, kad „Firebase“ funkcija sukonfigūruota tinkamai.

Įdiekite „Express Framework“:

Dabar įdiekime Expresssistemą savo projekte naudodami šią komandą:

npm i express

Dabar sukurkime API katalogą funkcijų kataloge. Tame kataloge sukursime failą pavadinimu todos.js. Pašalinkite viską iš index.jsir tada nukopijuokite ir įklijuokite šį kodą:

//index.js const functions = require('firebase-functions'); const app = require('express')(); const { getAllTodos } = require('./APIs/todos') app.get('/todos', getAllTodos); exports.api = functions.https.onRequest(app);

Maršrutui / todos priskyrėme funkciją getAllTodos . Taigi visi šio maršruto API skambučiai bus vykdomi per „getAllTodos“ funkciją. Dabar eikite į todos.jsfailą, esantį API kataloge, ir čia parašysime funkciją getAllTodos.

//todos.js exports.getAllTodos = (request, response) => { todos = [ { 'id': '1', 'title': 'greeting', 'body': 'Hello world from sharvin shah' }, { 'id': '2', 'title': 'greeting2', 'body': 'Hello2 world2 from sharvin shah' } ] return response.json(todos); }

Čia mes paskelbėme JSON objekto pavyzdį. Vėliau tai sužinosime iš „Firestore“. Tačiau kol kas tai grąžinsime. Dabar naudokite komandą tai įdiekite į „Firebase“ funkciją firebase deploy. Tai paklausnorint gauti leidimą ištrinti modulį helloworld - tiesiog įveskite y .

The following functions are found in your project but do not exist in your local source code: helloWorld Would you like to proceed with deletion? Selecting no will continue the rest of the deployments. (y/N) y

Tai atlikę eikite į „ Project Console“> „Funkcijos“ ir ten rasite API URL. API atrodys taip:

//-todoapp-.cloudfunctions.net/api

Dabar eikite į naršyklę ir nukopijuokite įklijuokite URL ir pridėkite / todos šio URL pabaigoje. Gausite tokią išvestį:

[ { 'id': '1', 'title': 'greeting', 'body': 'Hello world from sharvin shah' }, { 'id': '2', 'title': 'greeting2', 'body': 'Hello2 world2 from sharvin shah' } ]

„Firebase Firestore“:

Savo programai naudosime „Firebase Firestore“ kaip realaus laiko duomenų bazę. Dabar eikite į „ Console“> „Firebase Console“ duomenų bazė . Norėdami sukonfigūruoti gaisrinę, vadovaukitės toliau pateiktu gifu:

Kai konfigūracija bus atlikta, spustelėkite mygtuką Pradėti kolekciją ir nustatykite kolekcijos ID kaip būseną . Spustelėkite Pirmyn ir gausite šį iššokantį langą:

Nepaisykite „DocumentID“ rakto. Apie lauką, tipą ir vertę žiūrėkite žemiau pateiktą JSON. Atitinkamai atnaujinkite vertę:

{ Field: title, Type: String, Value: Hello World }, { Field: body, Type: String, Value: Hello folks I hope you are staying home... }, { Field: createtAt, type: timestamp, value: Add the current date and time here }

Paspauskite išsaugojimo mygtuką. Pamatysite, kad kolekcija ir dokumentas yra sukurti. Grįžkite į vietinę aplinką. Turime įdiegti, firebase-adminkuriame yra mums reikalingas „firestore“ paketas. Norėdami ją įdiegti, naudokite šią komandą:

npm i firebase-admin

Pagal funkcijų katalogą sukurkite katalogą pavadinimu util .Eikite į šį katalogą ir sukurkite failo pavadinimą admin.js. Šiame faile importuosime „Firebase“ administratoriaus paketą ir inicijuosime „firestore“ duomenų bazės objektą. Tai eksportuosime, kad kiti moduliai galėtų ja naudotis.

//admin.js const admin = require('firebase-admin'); admin.initializeApp(); const db = admin.firestore(); module.exports = { admin, db };

Dabar parašykime API, kad gautume šiuos duomenis. Eiti į todos.jspagal funkcijos> API kataloge. Pašalinkite seną kodą ir nukopijuokite ir įklijuokite toliau pateiktą kodą:

//todos.js const { db } = require('../util/admin'); exports.getAllTodos = (request, response) => { db .collection('todos') .orderBy('createdAt', 'desc') .get() .then((data) => { let todos = []; data.forEach((doc) => { todos.push({ todoId: doc.id, title: doc.data().title, body: doc.data().body, createdAt: doc.data().createdAt, }); }); return response.json(todos); }) .catch((err) => { console.error(err); return response.status(500).json({ error: err.code}); }); };

Čia mes gauname visus užduotis iš duomenų bazės ir persiunčiame klientui sąraše.

Taip pat galite paleisti programą vietoje naudodami firebase servekomandą, o ne kiekvieną kartą. Vykdydami šią komandą galite gauti klaidos informaciją apie prisijungimo duomenis. Norėdami ją išspręsti, atlikite toliau nurodytus veiksmus:

  1. Eikite į projekto nustatymus (viršutiniame kairiajame kampe esanti nustatymų piktograma)
  2. Eikite į paslaugų sąskaitų skirtuką  
  3. Žemiau bus galimybė sugeneruoti naują raktą . Spustelėkite šią parinktį ir jis atsisiųs failą su JSON plėtiniu.
  4. Šiuos kredencialus turime eksportuoti į savo komandinės eilutės sesiją. Norėdami tai padaryti, naudokite toliau pateiktą komandą:
export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/[FILE_NAME].json"

Po to paleiskite „Firebase serve“ komandą. Jei vis dar gaunate klaidos tada naudokite šią komandą: firebase login --reauth. Jis atidarys „Google“ prisijungimo puslapį naršyklėje. Kai prisijungsite, tai veiks be klaidų.

Kai vykdysite „Firebase serve“ komandą, URL rasite komandinės eilutės įrankio žurnaluose. Atidarykite šį URL naršyklėje ir pridėkite /todospo jo.

✔ functions[api]: http function initialized (//localhost:5000/todoapp-//api).

Savo naršyklėje gausite tokią JSON išvestį:

[ { "todoId":"W67t1kSMO0lqvjCIGiuI", "title":"Hello World", "body":"Hello folks I hope you are staying home...", "createdAt":{"_seconds":1585420200,"_nanoseconds":0 } } ]

Rašyti kitas API:

Atėjo laikas parašyti visas kitas „todo“ API, kurių reikės mūsų programai.

  1. Sukurti elementą „Todo“: eikite į index.jsfunkcijų katalogą. Importuoti „postOneTodo“ metodą pagal esamą „getAllTodos“. Taip pat tam metodui priskirkite POST maršrutą.
//index.js const { .., postOneTodo } = require('./APIs/todos') app.post('/todo', postOneTodo);

Eikite į todos.jsvidų funkcijų katalogo ir pridėkite naują metodą postOneTodopagal esamą getAllTodosmetodą.

//todos.js exports.postOneTodo = (request, response) => { if (request.body.body.trim() === '') { return response.status(400).json({ body: 'Must not be empty' }); } if(request.body.title.trim() === '') { return response.status(400).json({ title: 'Must not be empty' }); } const newTodoItem = { title: request.body.title, body: request.body.body, createdAt: new Date().toISOString() } db .collection('todos') .add(newTodoItem) .then((doc)=>{ const responseTodoItem = newTodoItem; responseTodoItem.id = doc.id; return response.json(responseTodoItem); }) .catch((err) => { response.status(500).json({ error: 'Something went wrong' }); console.error(err); }); };

Šiuo metodu mes įtraukiame naują „Todo“ į savo duomenų bazę. Jei mūsų kūno elementai yra tušti, mes pateiksime 400 atsakymą, arba mes pridėsime duomenis.

Paleiskite „firebase serve“ komandą ir atidarykite paštininko programą. Sukurkite naują užklausą ir pasirinkite metodo tipą kaip POST . Pridėkite URL ir JSON tipo turinį.

URL: //localhost:5000/todoapp-//api/todo METHOD: POST Body: { "title":"Hello World", "body": "We are writing this awesome API" }

Paspauskite siuntimo mygtuką ir gausite tokį atsakymą:

{ "title": "Hello World", "body": "We are writing this awesome API", "createdAt": "2020-03-29T12:30:48.809Z", "id": "nh41IgARCj8LPWBYzjU0" }

2. Ištrinti „Todo“ elementą: eikite į index.jsfunkcijų katalogą. Importuokite „deleteTodo“ metodą pagal esamą „postOneTodo“. Taip pat tam metodui priskirkite DELETE maršrutą.

//index.js const { .., deleteTodo } = require('./APIs/todos') app.delete('/todo/:todoId', deleteTodo);

Eikite į todos.jsir pridėkite naują metodą deleteTodopagal esamą postOneTodometodą.

//todos.js exports.deleteTodo = (request, response) => { const document = db.doc(`/todos/${request.params.todoId}`); document .get() .then((doc) => { if (!doc.exists) { return response.status(404).json({ error: 'Todo not found' }) } return document.delete(); }) .then(() => { response.json({ message: 'Delete successfull' }); }) .catch((err) => { console.error(err); return response.status(500).json({ error: err.code }); }); };

Šiuo metodu mes ištriname „Todo“ iš savo duomenų bazės. Vykdykite „Firebase serve“ komandą ir eikite į paštininką. Sukurkite naują užklausą, pasirinkite metodo tipą DELETE ir pridėkite URL.

URL: //localhost:5000/todoapp-//api/todo/ METHOD: DELETE

Paspauskite siuntimo mygtuką ir gausite tokį atsakymą:

{ "message": "Delete successfull" }

3. Redaguoti „Todo“ elementą: eikite į index.jsfunkcijų katalogą. Importuokite „editTodo“ metodą pagal esamą „deleteTodo“. Taip pat tam metodui priskirkite PUT maršrutą.

//index.js const { .., editTodo } = require('./APIs/todos') app.put('/todo/:todoId', editTodo);

Eikite į todos.jsir pridėkite naują metodą editTodopagal esamą deleteTodometodą.

//todos.js exports.editTodo = ( request, response ) => { if(request.body.todoId || request.body.createdAt){ response.status(403).json({message: 'Not allowed to edit'}); } let document = db.collection('todos').doc(`${request.params.todoId}`); document.update(request.body) .then(()=> { response.json({message: 'Updated successfully'}); }) .catch((err) => { console.error(err); return response.status(500).json({ error: err.code }); }); };

Šiuo metodu mes redaguojame „Todo“ iš savo duomenų bazės. Prisiminkite, kad čia neleidžiame vartotojui redaguoti laukų todoId arba sukurta. Vykdykite „Firebase serve“ komandą ir eikite į paštininką. Sukurkite naują užklausą, pasirinkite metodo tipą PUT ir pridėkite URL.

URL: //localhost:5000/todoapp-//api/todo/ METHOD: PUT

Paspauskite siuntimo mygtuką ir gausite tokį atsakymą:

{ "message": "Updated successfully" }

Katalogo struktūra iki šiol:

+-- firebase.json +-- functions | +-- API | +-- +-- todos.js | +-- util | +-- +-- admin.js | +-- index.js | +-- node_modules | +-- package-lock.json | +-- package.json | +-- .gitignore

Tai užbaigėme pirmąjį programos skyrių. Galite eiti išgerti kavos, padaryti pertrauką ir po to dirbsime kurdami „User API“.

2 skyrius: Vartotojo API kūrimas

Šiameskyriuje , mes ketiname sukurti šiuos komponentus:

  1. Vartotojo autentifikavimo (prisijungimo ir registracijos) API.
  2. GAUTI ir atnaujinti išsamią vartotojo informaciją API.
  3. Atnaujinkite vartotojo profilio paveikslėlio API.
  4. Esamos „Todo“ API užtikrinimas.

Šiame skyriuje įdiegtą vartotojo API kodą galite rasti šiame įsipareigojime.

Taigi pradėkime kurti vartotojo autentifikavimo API. Eikite į „ Firebase“ konsolę> Autentifikavimas.

Spustelėkite mygtuką Nustatyti prisijungimo metodą . Vartotojo patvirtinimui naudosime el. Paštą ir slaptažodį. Įjunkite parinktį El. Paštas / slaptažodis .

Dabar mes rankiniu būdu sukursime savo vartotoją. Pirmiausia sukursime „Login API“. Po to sukursime „Sign-Up API“.

Eikite į skirtuką „Vartotojai“ dalyje „Autentifikavimas“, užpildykite išsamią vartotojo informaciją ir spustelėkite mygtuką Pridėti vartotoją .

1. Vartotojo prisijungimo API:

Pirmiausia turime įdiegti firebasepaketą, kurį sudaro „ Firebase“ autentifikavimo biblioteka, naudodami šią komandą:

npm i firebase

Baigę diegti eikite į funkcijų> API katalogą. Čia sukursime users.jsfailą. Dabar „Inside“ index.jsimportuojame „loginUser“ metodą ir priskiriame jam POST maršrutą.

//index.js const { loginUser } = require('./APIs/users') // Users app.post('/login', loginUser);

Eikite į „ Project Settings“> „General“ ir rasite šią kortelę:

Pasirinkite žiniatinklio piktogramą ir vadovaukitės žemiau pateiktu gifu:

Pasirinkite tęsti konsolę . Tai padarę pamatysite JSON su „Firebase“ konfigūracija. Eikite į funkcijos> util katalogą ir sukurkite   config.jsfailą. Nukopijuokite ir įklijuokite šį kodą šiame faile:

// config.js module.exports = { apiKey: "............", authDomain: "........", databaseURL: "........", projectId: ".......", storageBucket: ".......", messagingSenderId: "........", appId: "..........", measurementId: "......." };

Pakeiskite ............vertėmis, kurias gaunate „ Firebase“ konsolėje> Projekto nustatymai> Bendrieji nustatymai > Jūsų programos> „Firebase SD“ fragmentas> konfigūracija .

Nukopijuokite ir įklijuokite users.jsfaile šį kodą :

// users.js const { admin, db } = require('../util/admin'); const config = require('../util/config'); const firebase = require('firebase'); firebase.initializeApp(config); const { validateLoginData, validateSignUpData } = require('../util/validators'); // Login exports.loginUser = (request, response) => { const user = { email: request.body.email, password: request.body.password } const { valid, errors } = validateLoginData(user); if (!valid) return response.status(400).json(errors); firebase .auth() .signInWithEmailAndPassword(user.email, user.password) .then((data) => { return data.user.getIdToken(); }) .then((token) => { return response.json({ token }); }) .catch((error) => { console.error(error); return response.status(403).json({ general: 'wrong credentials, please try again'}); }) };

Čia mes naudojame „firebase signInWithEmailAndPassword“ modulį, kad patikrintume, ar vartotojo pateikti kredencialai yra teisingi. Jei jie teisūs, mes siunčiame to vartotojo prieigos raktą arba 403 būseną su pranešimu „neteisingi prisijungimo duomenys“.

Dabar kurkime validators.jspagal funkcijų> util kataloge. Nukopijuokite ir įklijuokite šį kodą šiame faile:

// validators.js const isEmpty = (string) => { if (string.trim() === '') return true; else return false; }; exports.validateLoginData = (data) => { let errors = {}; if (isEmpty(data.email)) errors.email = 'Must not be empty'; if (isEmpty(data.password)) errors.password = 'Must not be empty'; return { errors, valid: Object.keys(errors).length === 0 ? true : false }; };

Tuo mūsų „ LoginAPI“ yra baigtas. Vykdykite firebase servekomandą ir eikite į paštininką. Sukurkite naują užklausą, pasirinkite metodo tipą kaip POST ir pridėkite URL bei turinį.

URL: //localhost:5000/todoapp-//api/login METHOD: POST Body: { "email":"Add email that is assigned for user in console", "password": "Add password that is assigned for user in console" }

Paspauskite paštininko mygtuką siųsti užklausą ir gausite tokį išvestį:

{ "token": ".........." }

Šį ženklą naudosime būsimoje dalyje, kad gautume išsamią vartotojo informaciją . Atminkite, kad šio prieigos rakto galiojimo laikas baigsis per 60 minučių . Norėdami sugeneruoti naują prieigos raktą, dar kartą naudokite šią API.

2. Vartotojo prisiregistravimo API:

Numatytasis „Firebase“ autentifikavimo mechanizmas leidžia jums saugoti tik tokią informaciją kaip el. Paštas, slaptažodis ir kt. Tačiau mums reikia daugiau informacijos, kad galėtume nustatyti, ar šis vartotojas turi tą vartotoją, kad jis galėtų atlikti skaitymo, atnaujinimo ir ištrynimo operacijas.

Norėdami pasiekti šį tikslą, mes sukursime naują kolekciją, vadinamą vartotojais . Šioje kolekcijoje mes išsaugosime vartotojo duomenis, kurie bus susieti su mažyliu pagal vartotojo vardą. Kiekvienas vartotojo vardas bus unikalus visiems platformos vartotojams.

Eikite į index.js. Importuojame „signUpUser“ metodą ir jam priskiriame POST maršrutą.

//index.js const { .., signUpUser } = require('./APIs/users') app.post('/signup', signUpUser);

Dabar eikite į validators.jsir pridėkite šį kodą po validateLoginDatametodu.

// validators.js const isEmail = (email) => { const emailRegEx = /^(([^()\[\]\\.,;:\[email protected]"]+(\.[^()\[\]\\.,;:\[email protected]"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; if (email.match(emailRegEx)) return true; else return false; }; exports.validateSignUpData = (data) => { let errors = {}; if (isEmpty(data.email)) { errors.email = 'Must not be empty'; } else if (!isEmail(data.email)) { errors.email = 'Must be valid email address'; } if (isEmpty(data.firstName)) errors.firstName = 'Must not be empty'; if (isEmpty(data.lastName)) errors.lastName = 'Must not be empty'; if (isEmpty(data.phoneNumber)) errors.phoneNumber = 'Must not be empty'; if (isEmpty(data.country)) errors.country = 'Must not be empty'; if (isEmpty(data.password)) errors.password = 'Must not be empty'; if (data.password !== data.confirmPassword) errors.confirmPassword = 'Passowrds must be the same'; if (isEmpty(data.username)) errors.username = 'Must not be empty'; return { errors, valid: Object.keys(errors).length === 0 ? true : false }; };

Dabar eikite į users.jsir pridėkite šį kodą po loginUsermoduliu.

// users.js exports.signUpUser = (request, response) => { const newUser = { firstName: request.body.firstName, lastName: request.body.lastName, email: request.body.email, phoneNumber: request.body.phoneNumber, country: request.body.country, password: request.body.password, confirmPassword: request.body.confirmPassword, username: request.body.username }; const { valid, errors } = validateSignUpData(newUser); if (!valid) return response.status(400).json(errors); let token, userId; db .doc(`/users/${newUser.username}`) .get() .then((doc) => { if (doc.exists) { return response.status(400).json({ username: 'this username is already taken' }); } else { return firebase .auth() .createUserWithEmailAndPassword( newUser.email, newUser.password ); } }) .then((data) => { userId = data.user.uid; return data.user.getIdToken(); }) .then((idtoken) => { token = idtoken; const userCredentials = { firstName: newUser.firstName, lastName: newUser.lastName, username: newUser.username, phoneNumber: newUser.phoneNumber, country: newUser.country, email: newUser.email, createdAt: new Date().toISOString(), userId }; return db .doc(`/users/${newUser.username}`) .set(userCredentials); }) .then(()=>{ return response.status(201).json({ token }); }) .catch((err) => { console.error(err); if (err.code === 'auth/email-already-in-use') { return response.status(400).json({ email: 'Email already in use' }); } else { return response.status(500).json({ general: 'Something went wrong, please try again' }); } }); }

Patvirtiname savo vartotojo duomenis, o po to išsiunčiame el. Laišką ir slaptažodį į „ Firebase“ modulį createUserWithEmailAndPassword, kad sukurtumėte vartotoją. Kai vartotojas bus sėkmingai sukurtas, mes išsaugosime vartotojo kredencialus duomenų bazėje.

Tai užbaigė mūsų „ SignUp“ API . Vykdykite firebase servekomandą ir eikite į paštininką. Sukurkite naują užklausą, pasirinkite metodo tipą kaip POST . Pridėkite URL ir turinį.

URL: //localhost:5000/todoapp-//api/signup METHOD: POST Body: { "firstName": "Add a firstName here", "lastName": "Add a lastName here", "email":"Add a email here", "phoneNumber": "Add a phone number here", "country": "Add a country here", "password": "Add a password here", "confirmPassword": "Add same password here", "username": "Add unique username here" }

Paspauskite paštininko mygtuką siųsti užklausą ir gausite tokį rezultatą:

{ "token": ".........." }

Dabar eikite į „ Firebase“ konsolę> Duomenų bazė ir pamatysite šį išvestį:

Kaip matote, mūsų vartotojo kolekcija sėkmingai sukurta su vienu dokumentu.

3. Įkelti vartotojo profilio nuotrauką:

Mūsų vartotojai galės įkelti savo profilio nuotrauką. Norėdami tai pasiekti, naudosime „Storage bucket“. Eikite į „ Firebase“ konsolę> Saugykla ir spustelėkite mygtuką Pradėti . Vadovaukitės toliau pateiktu GIF, kad sukonfigūruotumėte:

Dabar eikite į skirtuką Taisyklės, esančią skyriuje „Saugykla“, ir atnaujinkite prieigos prie grupės leidimą pagal toliau pateiktą vaizdą:

Norėdami įkelti profilio nuotrauką, naudosime paketą pavadinimu busboy. Norėdami įdiegti šį paketą, naudokite šią komandą:

npm i busboy

Eikite į index.js. Importuokite metodą uploadProfilePhoto žemiau esamo „signUpUser“ metodo. Taip pat tam metodui priskirkite POST maršrutą.

//index.js const auth = require('./util/auth'); const { .., uploadProfilePhoto } = require('./APIs/users') app.post('/user/image', auth, uploadProfilePhoto);

Čia pridėjome autentifikavimo sluoksnį, kad vaizdą galėtų įkelti tik su ta paskyra susietas vartotojas. Dabar sukurkite failą pavadinimu auth.jsir funkcijos> utils kataloge. Į failą nukopijuokite ir įklijuokite šį kodą:

// auth.js const { admin, db } = require('./admin'); module.exports = (request, response, next) => { let idToken; if (request.headers.authorization && request.headers.authorization.startsWith('Bearer ')) { idToken = request.headers.authorization.split('Bearer ')[1]; } else { console.error('No token found'); return response.status(403).json({ error: 'Unauthorized' }); } admin .auth() .verifyIdToken(idToken) .then((decodedToken) => { request.user = decodedToken; return db.collection('users').where('userId', '==', request.user.uid).limit(1).get(); }) .then((data) => { request.user.username = data.docs[0].data().username; request.user.imageUrl = data.docs[0].data().imageUrl; return next(); }) .catch((err) => { console.error('Error while verifying token', err); return response.status(403).json(err); }); };

Čia mes naudojame „Firebase“ patikrinkite „ IdItoken“ modulį, kad patvirtintume prieigos raktą. Po to mes dekoduojame vartotojo duomenis ir perduodame juos esamoje užklausoje.

Eikite į users.jsir po signupmetodu pridėkite šį kodą :

// users.js deleteImage = (imageName) => { const bucket = admin.storage().bucket(); const path = `${imageName}` return bucket.file(path).delete() .then(() => { return }) .catch((error) => { return }) } // Upload profile picture exports.uploadProfilePhoto = (request, response) => { const BusBoy = require('busboy'); const path = require('path'); const os = require('os'); const fs = require('fs'); const busboy = new BusBoy({ headers: request.headers }); let imageFileName; let imageToBeUploaded = {}; busboy.on('file', (fieldname, file, filename, encoding, mimetype) => { if (mimetype !== 'image/png' && mimetype !== 'image/jpeg') { return response.status(400).json({ error: 'Wrong file type submited' }); } const imageExtension = filename.split('.')[filename.split('.').length - 1]; imageFileName = `${request.user.username}.${imageExtension}`; const filePath = path.join(os.tmpdir(), imageFileName); imageToBeUploaded = { filePath, mimetype }; file.pipe(fs.createWriteStream(filePath)); }); deleteImage(imageFileName); busboy.on('finish', () => { admin .storage() .bucket() .upload(imageToBeUploaded.filePath, { resumable: false, metadata: { metadata: { contentType: imageToBeUploaded.mimetype } } }) .then(() => { const imageUrl = `//firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${imageFileName}?alt=media`; return db.doc(`/users/${request.user.username}`).update({ imageUrl }); }) .then(() => { return response.json({ message: 'Image uploaded successfully' }); }) .catch((error) => { console.error(error); return response.status(500).json({ error: error.code }); }); }); busboy.end(request.rawBody); };

Tai užbaigė mūsų profilio paveikslėlio įkėlimo API . Vykdykite firebase servekomandą ir eikite į paštininką. Sukurkite naują užklausą, pasirinkite metodo tipą kaip POST , pridėkite URL, o turinio skyriuje pasirinkite tipą kaip formos duomenys.

Užklausa yra apsaugota, todėl taip pat turėsite išsiųsti turėtojo ženklą . Jei norite išsiųsti atpažinimo ženklą, vėl prisijunkite, jei galiojimo laikas pasibaigęs. Po to „ Postman App“> skirtuke „Leidimas“> „Type“> „Bearer Token“ ir žetono skyriuje įklijuokite žetoną.

URL: //localhost:5000/todoapp-//api/user/image METHOD: GET Body: { REFER THE IMAGE down below }

Paspauskite paštininko mygtuką siųsti užklausą ir gausite tokį rezultatą:

{ "message": "Image uploaded successfully" }

4. Gaukite vartotojo informaciją:

Čia mes gauname savo vartotojo duomenis iš duomenų bazės. Eikite į index.jsir importuokite metodą getUserDetail ir priskirkite jam GET maršrutą.

// index.js const { .., getUserDetail } = require('./APIs/users') app.get('/user', auth, getUserDetail);

Dabar eikite į users.jsir pridėkite šį kodą po uploadProfilePhotomodulio:

// users.js exports.getUserDetail = (request, response) => { let userData = {}; db .doc(`/users/${request.user.username}`) .get() .then((doc) => { if (doc.exists) { userData.userCredentials = doc.data(); return response.json(userData); } }) .catch((error) => { console.error(error); return response.status(500).json({ error: error.code }); }); }

Norėdami gauti išsamią vartotojo informaciją, mes naudojame „Firebase doc“ (). Get () modulį. Tai užbaigė mūsų GET vartotojo informacijos API . Vykdykite firebase servekomandą ir eikite į paštininką. Sukurkite naują užklausą, pasirinkite metodo tipą: GET ir pridėkite URL bei turinį.

Užklausa yra apsaugota, todėl taip pat turėsite išsiųsti turėtojo ženklą . Jei norite išsiųsti atpažinimo ženklą, vėl prisijunkite, jei galiojimo laikas pasibaigęs.

URL: //localhost:5000/todoapp-//api/user METHOD: GET

Paspauskite paštininko mygtuką siųsti užklausą ir gausite tokį rezultatą:

{ "userCredentials": { "phoneNumber": "........", "email": "........", "country": "........", "userId": "........", "username": "........", "createdAt": "........", "lastName": "........", "firstName": "........" } }

5. Atnaujinkite išsamią vartotojo informaciją:

Dabar pridėkime funkciją, kad būtų atnaujinta vartotojo informacija. Eikite į index.jsir nukopijuokite ir įklijuokite šį kodą:

// index.js const { .., updateUserDetails } = require('./APIs/users') app.post('/user', auth, updateUserDetails);

Dabar eikite į users.jsir pridėkite updateUserDetailsmodulį žemiau esamo getUserDetails:

// users.js exports.updateUserDetails = (request, response) => { let document = db.collection('users').doc(`${request.user.username}`); document.update(request.body) .then(()=> { response.json({message: 'Updated successfully'}); }) .catch((error) => { console.error(error); return response.status(500).json({ message: "Cannot Update the value" }); }); }

Čia mes naudojame „Firebase“ atnaujinimo metodą. Tai atlikus mūsų atnaujinta naudotojo informacijos API yra baigta. Atlikdami tą patį prašymą, atlikite tą pačią procedūrą, kaip ir naudodami aukščiau pateiktą API gauti vartotojo informaciją. Čia prašyme pridėkite turinį ir metodą kaip POST.

URL: //localhost:5000/todoapp-//api/user METHOD: POST Body : { // You can edit First Name, last Name and country // We will disable other Form Tags from our UI }

Paspauskite paštininko mygtuką siųsti užklausą ir gausite tokį rezultatą:

{ "message": "Updated successfully" }

6. „Todo“ API užtikrinimas:

Norėdami apsaugoti „Todo“ API, kad prie jos galėtų prisijungti tik pasirinktas vartotojas, atliksime keletą pakeitimų esamame kode. Pirma, mes atnaujinsime savo index.jsveiksmus taip:

// index.js // Todos app.get('/todos', auth, getAllTodos); app.get('/todo/:todoId', auth, getOneTodo); app.post('/todo',auth, postOneTodo); app.delete('/todo/:todoId',auth, deleteTodo); app.put('/todo/:todoId',auth, editTodo);

Atnaujinome visus „ Todo“ maršrutus pridėdami auth, kad visiems API skambučiams reikės prieigos rakto ir prie jų galėtų prisijungti tik konkretus vartotojas.

Po to pereiti prie todos.jspagal funkcijos> API kataloge.

  1. Sukurti Todo API: Atidarykite todos.jsir pagal postOneTodo metodą pridėkite raktą vardą taip:
const newTodoItem = { .., username: request.user.username, .. }

2. GAUTI „Todos“ API: atidarykite todos.jsir naudodami metodą getAllTodos pridėkite sąlygą „where“ taip:

db .collection('todos') .where('username', '==', request.user.username) .orderBy('createdAt', 'desc')

Paleiskite „Firebase“ tarnybą ir išbandykite mūsų GET API. Nepamirškite išsiųsti turėtojo žetono. Čia gausite atsakymo klaidą taip:

{ "error": 9 }

Eikite į komandinę eilutę ir pamatysite užregistruotas šias eilutes:

i functions: Beginning execution of "api"> Error: 9 FAILED_PRECONDITION: The query requires an index. You can create it here: > at callErrorFromStatus

Atidarykite tai naršyklėje ir spustelėkite sukurti indeksą.

Kai indeksas bus sudarytas, siųskite užklausą dar kartą ir gausite tokį išvestį:

[ { "todoId": "......", "title": "......", "username": "......", "body": "......", "createdAt": "2020-03-30T13:01:58.478Z" } ]

3.   Ištrinti „Todo“ API: atidarykite todos.jsir naudodami „ deleteTodo“ metodą pridėkite šią sąlygą. Įtraukite šią sąlygą į document.get (). Tada () užklausą po sąlyga ! Doc.exist .

.. if(doc.data().username !== request.user.username){ return response.status(403).json({error:"UnAuthorized"}) }

Katalogų struktūra iki šiol:

+-- firebase.json +-- functions | +-- API | +-- +-- todos.js | +-- +-- users.js | +-- util | +-- +-- admin.js | +-- +-- auth.js | +-- +-- validators.js | +-- index.js | +-- node_modules | +-- package-lock.json | +-- package.json | +-- .gitignore

Tai užbaigėme savo API programinę įrangą. Padarykite pertrauką, išgerkite kavos, o po to mes pradėsime kurti savo programos priekinę dalį

3 skyrius: Vartotojo informacijos suvestinė

Šiameskyriuje , mes ketiname sukurti šiuos komponentus:

  1. Konfigūruokite „ReactJS“ ir „Material UI“.
  2. Prisijungimo ir prisiregistravimo formos kūrimas.
  3. Pastato sąskaitos skyrius.

Šiame skyriuje įdiegtą vartotojo informacijos suvestinės kodą galite rasti šiame įsipareigojime.

1. Konfigūruokite „ReactJS“ ir „Material UI“:

Mes naudosime „sukurti-reaguoti“ programos šabloną. Tai suteikia mums pagrindinę programos kūrimo struktūrą. Norėdami jį įdiegti, naudokite šią komandą:

npm install -g create-react-app

Eikite į projekto šakninį aplanką, kuriame yra funkcijų katalogas. Inicijuokite mūsų priekinę programą naudodami šią komandą:

create-react-app view

Nepamirškite naudoti versijos v16.13.1„ReactJS“ biblioteka .

Kai diegimas bus baigtas, komandų eilutės žurnaluose pamatysite:

cd view npm start Happy hacking!

Tai sukonfigūravome savo „React“ programą. Gausite tokią katalogo struktūrą:

+-- firebase.json +-- functions { This Directory consists our API logic } +-- view { This Directory consists our FrontEnd Compoenents } +-- .firebaserc +-- .gitignore

Dabar paleiskite programą naudodami komandą npm start. Eikite į naršyklę //localhost:3000/ir pamatysite šį išvestį:

Dabar mes pašalinsime visus nereikalingus komponentus. Eikite į rodinių katalogą ir pašalinkite visus failuskurių priekyje yra [Pašalinti] . Norėdami tai padaryti, žiūrėkite žemiau esančią katalogų medžio struktūrą.

+-- README.md [ Remove ] +-- package-lock.json +-- package.json +-- node_modules +-- .gitignore +-- public | +-- favicon.ico [ Remove ] | +-- index.html | +-- logo192.png [ Remove ] | +-- logo512.png [ Remove ] | +-- manifest.json | +-- robots.txt +-- src | +-- App.css | +-- App.test.js | +-- index.js | +-- serviceWorker.js | +-- App.js | +-- index.css [ Remove ] | +-- logo.svg [ Remove ] | +-- setupTests.js

Eikite į index.htmlviešąjį katalogą ir pašalinkite šias eilutes:

Dabar eikite į App.jskatalogą src ir pakeiskite seną kodą šiuo kodu:

import React from 'react'; function App() { return ( ); } export default App;

Eikite į index.jsir pašalinkite šį importavimą:

import './index.css'

Aš neištryniau App.cssir nenaudoju jos šioje programoje. Bet jei norite jį ištrinti ar naudoti, galite tai padaryti laisvai.

Eikite į naršyklę //localhost:3000/ir gausite tuščią ekrano išvestį.

Norėdami įdiegti „Material UI“, eikite į rodinio katalogą ir nukopijuokite ir įklijuokite šią komandą terminale:

npm install @material-ui/core

Nepamirškite naudoti „Material UI“ bibliotekos v4.9.8 versijos .

2. Prisijungimo forma:

Norėdami sukurti prisijungimo formą, eikite į App.js. Viršuje App.jspridėkite šį importą:

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; import login from './pages/login';

„ TodoApp“ maršrutams priskirti naudojame „ Switch and Route“ . Dabar pridėsime tik / login maršrutą ir priskirsime jam prisijungimo komponentą.

// App.js 

Sukurti puslapiai katalogą pagal esamą vaizdo kataloge ir failą pavadinimu login.jspagal puslapių katalogą.

Importuosime „Material UI“ komponentus ir „Axios“ paketą login.js:

// login.js // Material UI components import React, { Component } from 'react'; import Avatar from '@material-ui/core/Avatar'; import Button from '@material-ui/core/Button'; import CssBaseline from '@material-ui/core/CssBaseline'; import TextField from '@material-ui/core/TextField'; import Link from '@material-ui/core/Link'; import Grid from '@material-ui/core/Grid'; import LockOutlinedIcon from '@material-ui/icons/LockOutlined'; import Typography from '@material-ui/core/Typography'; import withStyles from '@material-ui/core/styles/withStyles'; import Container from '@material-ui/core/Container'; import CircularProgress from '@material-ui/core/CircularProgress'; import axios from 'axios';

Prie savo prisijungimo puslapio pridėsime šiuos stilius:

// login.js const styles = (theme) => ({ paper: { marginTop: theme.spacing(8), display: 'flex', flexDirection: 'column', alignItems: 'center' }, avatar: { margin: theme.spacing(1), backgroundColor: theme.palette.secondary.main }, form: { width: '100%', marginTop: theme.spacing(1) }, submit: { margin: theme.spacing(3, 0, 2) }, customError: { color: 'red', fontSize: '0.8rem', marginTop: 10 }, progess: { position: 'absolute' } });

Mes sukursime klasę, pavadintą prisijungimas, kurioje bus forma, ir joje pateiksime tvarkytuvą.

// login.js class login extends Component { constructor(props) { super(props); this.state = { email: '', password: '', errors: [], loading: false }; } componentWillReceiveProps(nextProps) { if (nextProps.UI.errors) { this.setState({ errors: nextProps.UI.errors }); } } handleChange = (event) => { this.setState({ [event.target.name]: event.target.value }); }; handleSubmit = (event) => { event.preventDefault(); this.setState({ loading: true }); const userData = { email: this.state.email, password: this.state.password }; axios .post('/login', userData) .then((response) => { localStorage.setItem('AuthToken', `Bearer ${response.data.token}`); this.setState({ loading: false, }); this.props.history.push('/'); }) .catch((error) => { this.setState({ errors: error.response.data, loading: false }); }); }; render() { const { classes } = this.props; const { errors, loading } = this.state; return ( Login      Sign In {loading && }     {"Don't have an account? Sign Up"}    {errors.general && (  {errors.general}  )} ); } }

Šio failo pabaigoje pridėkite šį eksportą:

export default withStyles(styles)(login); 

Pridėkite mūsų „Firebase“ funkcijų URL, kad peržiūrėtumėte> package.json taip:

Atminkite: pridėkite raktą, pavadintą tarpiniu serveriu po esamu naršyklių sąrašo JSON objektu
"proxy": "//-todoapp-.cloudfunctions.net/api"

Įdiekite „ Axios“ ir „ material“ piktogramų paketą naudodami šias komandas:

// Axios command: npm i axios // Material Icons: npm install @material-ui/icons

Pridėjome prisijungimo maršrutą App.js. Į login.jsmes sukūrėme klasės komponentas, kuris tvarko valstybė, siunčia pašto prašymą prisijungimo API naudojant Aksijo paketą. Jei užklausa yra sėkminga, mes saugome prieigos raktą. Jei atsakyme pastebime klaidų, jas paprasčiausiai pateikiame vartotojo sąsajoje.

Eikite į naršyklę adresu //localhost:3000/loginir pamatysite šią prisijungimo sąsają.

Pabandykite užpildyti neteisingus prisijungimo duomenis arba išsiųsti tuščią užklausą ir gausite klaidas. Siųskite galiojančią užklausą. Eikite į „ Developer Console“> „Application“ . Pamatysite, kad vartotojų prieigos raktas yra saugomas vietinėje saugykloje. Kai prisijungimas bus sėkmingas, būsime nukreipti atgal į pagrindinį puslapį.

3. Registracijos forma:

Norėdami sukurti registracijos formą, eikite į App.jsesamą Routekomponentą ir atnaujinkite toliau pateiktą eilutę:

// App.js 

Nepamirškite importuoti:

// App.js import signup from './pages/signup';

Sukurti failą pavadinimu signup.jspagal puslapių katalogą .

„Signup.js“ viduje importuosime „Material UI“ ir „Axios“ paketą:

// signup.js import React, { Component } from 'react'; import Avatar from '@material-ui/core/Avatar'; import Button from '@material-ui/core/Button'; import CssBaseline from '@material-ui/core/CssBaseline'; import TextField from '@material-ui/core/TextField'; import Link from '@material-ui/core/Link'; import Grid from '@material-ui/core/Grid'; import LockOutlinedIcon from '@material-ui/icons/LockOutlined'; import Typography from '@material-ui/core/Typography'; import Container from '@material-ui/core/Container'; import withStyles from '@material-ui/core/styles/withStyles'; import CircularProgress from '@material-ui/core/CircularProgress'; import axios from 'axios';

Prie savo registracijos puslapio pridėsime šiuos stilius:

// signup.js const styles = (theme) => ({ paper: { marginTop: theme.spacing(8), display: 'flex', flexDirection: 'column', alignItems: 'center' }, avatar: { margin: theme.spacing(1), backgroundColor: theme.palette.secondary.main }, form: { width: '100%', // Fix IE 11 issue. marginTop: theme.spacing(3) }, submit: { margin: theme.spacing(3, 0, 2) }, progess: { position: 'absolute' } }); 

Mes sukursime klasę, pavadintą registracija, kurioje bus forma, ir joje pateiksime tvarkytuvą.

// signup.js class signup extends Component { constructor(props) { super(props); this.state = { firstName: '', lastName: '', phoneNumber: '', country: '', username: '', email: '', password: '', confirmPassword: '', errors: [], loading: false }; } componentWillReceiveProps(nextProps) { if (nextProps.UI.errors) { this.setState({ errors: nextProps.UI.errors }); } } handleChange = (event) => { this.setState({ [event.target.name]: event.target.value }); }; handleSubmit = (event) => { event.preventDefault(); this.setState({ loading: true }); const newUserData = { firstName: this.state.firstName, lastName: this.state.lastName, phoneNumber: this.state.phoneNumber, country: this.state.country, username: this.state.username, email: this.state.email, password: this.state.password, confirmPassword: this.state.confirmPassword }; axios .post('/signup', newUserData) .then((response) => { localStorage.setItem('AuthToken', `${response.data.token}`); this.setState({ loading: false, }); this.props.history.push('/'); }) .catch((error) => { this.setState({ errors: error.response.data, loading: false }); }); }; render() { const { classes } = this.props; const { errors, loading } = this.state; return ( Sign up                              Sign Up {loading && }     Already have an account? Sign in ); } }

Šio failo pabaigoje pridėkite šį eksportą:

export default withStyles(styles)(signup); 

Registravimo komponento logika yra tokia pati kaip prisijungimo komponento. Eikite į naršyklę adresu //localhost:3000/signupir pamatysite šią registracijos vartotojo sąsają. Kai registracija bus sėkminga, būsime nukreipti atgal į pagrindinį puslapį.

Pabandykite užpildyti neteisingus prisijungimo duomenis arba išsiųsti tuščią užklausą ir gausite klaidas. Siųskite galiojančią užklausą. Eikite į „ Developer Console“> „Application“ . Pamatysite, kad vartotojų prieigos raktas yra saugomas vietinėje saugykloje.

4. Sąskaitos skyrius:

Norėdami sukurti paskyros puslapį, pirmiausia turėsime sukurti savo pagrindinį puslapį, iš kurio įkelsime paskyros skyrių . Eikite į App.jsir atnaujinkite šį maršrutą:

// App.js 

Nepamirškite importo:

// App.js import home from './pages/home';

Sukurkite naują failą pavadinimu home.js. Šis failas bus mūsų programos rodyklė. Skiltys „Paskyra“ ir „Todo“ šiame puslapyje įkeliamos pagal mygtuko paspaudimą.

Importuokite „Material UI“ paketus, „Axios“ paketą, mūsų pasirinktinę paskyrą, tikrus komponentus ir autentifikavimo tarpines programas.

// home.js import React, { Component } from 'react'; import axios from 'axios'; import Account from '../components/account'; import Todo from '../components/todo'; import Drawer from '@material-ui/core/Drawer'; import AppBar from '@material-ui/core/AppBar'; import CssBaseline from '@material-ui/core/CssBaseline'; import Toolbar from '@material-ui/core/Toolbar'; import List from '@material-ui/core/List'; import Typography from '@material-ui/core/Typography'; import Divider from '@material-ui/core/Divider'; import ListItem from '@material-ui/core/ListItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; import withStyles from '@material-ui/core/styles/withStyles'; import AccountBoxIcon from '@material-ui/icons/AccountBox'; import NotesIcon from '@material-ui/icons/Notes'; import Avatar from '@material-ui/core/avatar'; import ExitToAppIcon from '@material-ui/icons/ExitToApp'; import CircularProgress from '@material-ui/core/CircularProgress'; import { authMiddleWare } from '../util/auth'

Savo stalčiaus plotį nustatysime taip:

const drawerWidth = 240;

Į savo pagrindinį puslapį įtrauksime šį stilių:

const styles = (theme) => ({ root: { display: 'flex' }, appBar: { zIndex: theme.zIndex.drawer + 1 }, drawer: { width: drawerWidth, flexShrink: 0 }, drawerPaper: { width: drawerWidth }, content: { flexGrow: 1, padding: theme.spacing(3) }, avatar: { height: 110, width: 100, flexShrink: 0, flexGrow: 0, marginTop: 20 }, uiProgess: { position: 'fixed', zIndex: '1000', height: '31px', width: '31px', left: '50%', top: '35%' }, toolbar: theme.mixins.toolbar });

Sukursime klasę pavadinimu namai. Ši klasė turės API skambutį, kad gautų vartotojo profilio nuotrauką, vardą ir pavardę. Taip pat ji turės logiką pasirinkti, kurį komponentą rodyti - „Todo“ ar „Account“:

class home extends Component { state = { render: false }; loadAccountPage = (event) => { this.setState({ render: true }); }; loadTodoPage = (event) => { this.setState({ render: false }); }; logoutHandler = (event) => { localStorage.removeItem('AuthToken'); this.props.history.push('/login'); }; constructor(props) { super(props); this.state = { firstName: '', lastName: '', profilePicture: '', uiLoading: true, imageLoading: false }; } componentWillMount = () => { authMiddleWare(this.props.history); const authToken = localStorage.getItem('AuthToken'); axios.defaults.headers.common = { Authorization: `${authToken}` }; axios .get('/user') .then((response) => { console.log(response.data); this.setState({ firstName: response.data.userCredentials.firstName, lastName: response.data.userCredentials.lastName, email: response.data.userCredentials.email, phoneNumber: response.data.userCredentials.phoneNumber, country: response.data.userCredentials.country, username: response.data.userCredentials.username, uiLoading: false, profilePicture: response.data.userCredentials.imageUrl }); }) .catch((error) => { if(error.response.status === 403) { this.props.history.push('/login') } console.log(error); this.setState({ errorMsg: 'Error in retrieving the data' }); }); }; render() { const { classes } = this.props; if (this.state.uiLoading === true) { return ( {this.state.uiLoading && } ); } else { return ( TodoApp 

{' '} {this.state.firstName} {this.state.lastName}

{' '} {' '} {' '} {' '} {' '} {' '} {this.state.render ? : } ); } } }

Čia kode pamatysite, kad authMiddleWare(this.props.history);jis naudojamas. Ši tarpinė programinė įranga patikrina, ar authToken yra nulinis. Jei taip, tai nustums vartotoją į login.js. Tai pridėta, kad mūsų vartotojas negalėtų pasiekti /maršruto neprisiregistravęs ar neprisijungęs. Šio failo pabaigoje pridėkite šį eksportą:

export default withStyles(styles)(home); 

Dabar jums įdomu, ką veikia šis kodas home.js?

 {this.state.render ?  : } 

Tai tikrina pateikimo būseną, kurią nustatome spustelėjus mygtuką. Sukurkime komponentų katalogą, o po juo sukurkime du failus: account.jsir todo.js.

Sukurkime katalogą pavadinimu util ir failą, pavadintą auth.jstame kataloge. Nukopijuokite ir įklijuokite šį kodą auth.js:

export const authMiddleWare = (history) => { const authToken = localStorage.getItem('AuthToken'); if(authToken === null){ history.push('/login') } }

Laikui todo.jsfailą, mes tiesiog parašysime klasę, kurioje bus pateiktas tekstas Sveiki, aš esu mažas . Kitame skyriuje dirbsime su savo darbais:

import React, { Component } from 'react' import withStyles from '@material-ui/core/styles/withStyles'; import Typography from '@material-ui/core/Typography'; const styles = ((theme) => ({ content: { flexGrow: 1, padding: theme.spacing(3), }, toolbar: theme.mixins.toolbar, }) ); class todo extends Component { render() { const { classes } = this.props; return ( Hello I am todo   ) } } export default (withStyles(styles)(todo));

Dabar atėjo laikas paskyros skyriui. Importuokite „Material UI“, „clsx“, „axios“ ir „authmiddleWare“ įrankius į mus account.js.

// account.js import React, { Component } from 'react'; import withStyles from '@material-ui/core/styles/withStyles'; import Typography from '@material-ui/core/Typography'; import CircularProgress from '@material-ui/core/CircularProgress'; import CloudUploadIcon from '@material-ui/icons/CloudUpload'; import { Card, CardActions, CardContent, Divider, Button, Grid, TextField } from '@material-ui/core'; import clsx from 'clsx'; import axios from 'axios'; import { authMiddleWare } from '../util/auth';

Prie savo paskyros puslapio pridėsime šį stilių:

// account.js const styles = (theme) => ({ content: { flexGrow: 1, padding: theme.spacing(3) }, toolbar: theme.mixins.toolbar, root: {}, details: { display: 'flex' }, avatar: { height: 110, width: 100, flexShrink: 0, flexGrow: 0 }, locationText: { paddingLeft: '15px' }, buttonProperty: { position: 'absolute', top: '50%' }, uiProgess: { position: 'fixed', zIndex: '1000', height: '31px', width: '31px', left: '50%', top: '35%' }, progess: { position: 'absolute' }, uploadButton: { marginLeft: '8px', margin: theme.spacing(1) }, customError: { color: 'red', fontSize: '0.8rem', marginTop: 10 }, submitButton: { marginTop: '10px' } });

Mes sukursime klasės komponentą, pavadintą paskyra. Kol kas tiesiog nukopijuokite ir įklijuokite šį kodą:

// account.js class account extends Component { constructor(props) { super(props); this.state = { firstName: '', lastName: '', email: '', phoneNumber: '', username: '', country: '', profilePicture: '', uiLoading: true, buttonLoading: false, imageError: '' }; } componentWillMount = () => { authMiddleWare(this.props.history); const authToken = localStorage.getItem('AuthToken'); axios.defaults.headers.common = { Authorization: `${authToken}` }; axios .get('/user') .then((response) => { console.log(response.data); this.setState({ firstName: response.data.userCredentials.firstName, lastName: response.data.userCredentials.lastName, email: response.data.userCredentials.email, phoneNumber: response.data.userCredentials.phoneNumber, country: response.data.userCredentials.country, username: response.data.userCredentials.username, uiLoading: false }); }) .catch((error) => { if (error.response.status === 403) { this.props.history.push('/login'); } console.log(error); this.setState({ errorMsg: 'Error in retrieving the data' }); }); }; handleChange = (event) => { this.setState({ [event.target.name]: event.target.value }); }; handleImageChange = (event) => { this.setState({ image: event.target.files[0] }); }; profilePictureHandler = (event) => { event.preventDefault(); this.setState({ uiLoading: true }); authMiddleWare(this.props.history); const authToken = localStorage.getItem('AuthToken'); let form_data = new FormData(); form_data.append('image', this.state.image); form_data.append('content', this.state.content); axios.defaults.headers.common = { Authorization: `${authToken}` }; axios .post('/user/image', form_data, { headers: { 'content-type': 'multipart/form-data' } }) .then(() => { window.location.reload(); }) .catch((error) => { if (error.response.status === 403) { this.props.history.push('/login'); } console.log(error); this.setState({ uiLoading: false, imageError: 'Error in posting the data' }); }); }; updateFormValues = (event) => { event.preventDefault(); this.setState({ buttonLoading: true }); authMiddleWare(this.props.history); const authToken = localStorage.getItem('AuthToken'); axios.defaults.headers.common = { Authorization: `${authToken}` }; const formRequest = { firstName: this.state.firstName, lastName: this.state.lastName, country: this.state.country }; axios .post('/user', formRequest) .then(() => { this.setState({ buttonLoading: false }); }) .catch((error) => { if (error.response.status === 403) { this.props.history.push('/login'); } console.log(error); this.setState({ buttonLoading: false }); }); }; render() { const { classes, ...rest } = this.props; if (this.state.uiLoading === true) { return ( {this.state.uiLoading && }  ); } else { return ( {this.state.firstName} {this.state.lastName}  

Šio failo pabaigoje pridėkite šį eksportą:

export default withStyles(styles)(account); 

Be account.jsyra daug komponentų, naudojamų. Pirmiausia pažiūrėkime, kaip atrodo mūsų programa. Po to aš paaiškinsiu visus naudojamus komponentus ir kodėl jie naudojami.

Eikite į naršyklę ir, jei jūsų prieigos raktas nebegalios, jis nukreips jus į   loginpuslapį. Pridėkite savo informaciją ir vėl prisijunkite. Tai padarę, eikite į skirtuką Paskyra ir rasite šią vartotojo sąsają:

Sąskaitos skyriuje yra 3 tvarkytojai:

  1. KomponentasWillMount : Tai yra „React“ integruotas gyvavimo ciklo metodas. Mes naudojame jį duomenims įkelti prieš pateikimo gyvavimo ciklą ir atnaujiname būsenos reikšmes.
  2. „ProfilePictureUpdate“: tai yra mūsų pasirinktas tvarkytuvas, kurį naudojame, kad kai vartotojas spustelės mygtuką „Įkelti nuotrauką“, jis nusiųs duomenis į serverį ir iš naujo įkels puslapį, kad būtų rodoma vartotojo nauja profilio nuotrauka.
  3. updateFormValues: Tai taip pat yra mūsų pasirinktinis tvarkytuvas, skirtas atnaujinti vartotojo duomenis. Čia vartotojas gali atnaujinti savo vardą, pavardę ir šalį. Mes neleidžiame atnaujinti el. Pašto ir vartotojo vardų, nes mūsų vidinė logika priklauso nuo šių raktų.

Išskyrus šiuos 3 tvarkytuvus, tai yra formos puslapis, kurio viršuje yra stilius. Čia yra katalogų struktūra iki šio taško rodinio aplanke:

+-- public +-- src | +-- components | +-- +-- todo.js | +-- +-- account.js | +-- pages | +-- +-- home.js | +-- +-- login.js | +-- +-- signup.js | +-- util | +-- +-- auth.js | +-- README.md | +-- package-lock.json | +-- package.json | +-- .gitignore

Tai užbaigėme savo paskyros informacijos suvestinę. Dabar eikite išgerti kavos, padarykite pertrauką ir kitame skyriuje pastatysime „Todo“ informacijos suvestinę.

4 skyrius: „Todo“ informacijos suvestinė

Šiameskyriuje , mes sukursime šių „Todos“ informacijos suvestinės funkcijų vartotojo sąsają:

  1. Pridėti „Todo“:
  2. Gaukite visas užduotis:
  3. Ištrinti užduotį
  4. Redaguoti užduotį
  5. Gaukite tikrovę
  6. Taikoma tema

Šiame skyriuje įdiegtą „Todo“ informacijos suvestinės kodą galite rasti šiame įsipareigojime.

Eiti į todos.jspagal komponentų kataloge. Prie esamo importo pridėkite šį importą:

import Button from '@material-ui/core/Button'; import Dialog from '@material-ui/core/Dialog'; import AddCircleIcon from '@material-ui/icons/AddCircle'; import AppBar from '@material-ui/core/AppBar'; import Toolbar from '@material-ui/core/Toolbar'; import IconButton from '@material-ui/core/IconButton'; import CloseIcon from '@material-ui/icons/Close'; import Slide from '@material-ui/core/Slide'; import TextField from '@material-ui/core/TextField'; import Grid from '@material-ui/core/Grid'; import Card from '@material-ui/core/Card'; import CardActions from '@material-ui/core/CardActions'; import CircularProgress from '@material-ui/core/CircularProgress'; import CardContent from '@material-ui/core/CardContent'; import MuiDialogTitle from '@material-ui/core/DialogTitle'; import MuiDialogContent from '@material-ui/core/DialogContent'; import axios from 'axios'; import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; import { authMiddleWare } from '../util/auth';

Taip pat esamuose stiliaus komponentuose turime pridėti šiuos CSS elementus:

const styles = (theme) => ({ .., // Existing CSS elements title: { marginLeft: theme.spacing(2), flex: 1 }, submitButton: { display: 'block', color: 'white', textAlign: 'center', position: 'absolute', top: 14, right: 10 }, floatingButton: { position: 'fixed', bottom: 0, right: 0 }, form: { width: '98%', marginLeft: 13, marginTop: theme.spacing(3) }, toolbar: theme.mixins.toolbar, root: { minWidth: 470 }, bullet: { display: 'inline-block', margin: '0 2px', transform: 'scale(0.8)' }, pos: { marginBottom: 12 }, uiProgess: { position: 'fixed', zIndex: '1000', height: '31px', width: '31px', left: '50%', top: '35%' }, dialogeStyle: { maxWidth: '50%' }, viewRoot: { margin: 0, padding: theme.spacing(2) }, closeButton: { position: 'absolute', right: theme.spacing(1), top: theme.spacing(1), color: theme.palette.grey[500] } });

Pridėsime iššokančiojo dialogo lango perėjimą:

const Transition = React.forwardRef(function Transition(props, ref) { return ; });

Pašalinkite esamą „Todo“ klasę ir nukopijuokite ir įklijuokite šią klasę:

class todo extends Component { constructor(props) { super(props); this.state = { todos: '', title: '', body: '', todoId: '', errors: [], open: false, uiLoading: true, buttonType: '', viewOpen: false }; this.deleteTodoHandler = this.deleteTodoHandler.bind(this); this.handleEditClickOpen = this.handleEditClickOpen.bind(this); this.handleViewOpen = this.handleViewOpen.bind(this); } handleChange = (event) => { this.setState({ [event.target.name]: event.target.value }); }; componentWillMount = () => { authMiddleWare(this.props.history); const authToken = localStorage.getItem('AuthToken'); axios.defaults.headers.common = { Authorization: `${authToken}` }; axios .get('/todos') .then((response) => { this.setState({ todos: response.data, uiLoading: false }); }) .catch((err) => { console.log(err); }); }; deleteTodoHandler(data) { authMiddleWare(this.props.history); const authToken = localStorage.getItem('AuthToken'); axios.defaults.headers.common = { Authorization: `${authToken}` }; let todoId = data.todo.todoId; axios .delete(`todo/${todoId}`) .then(() => { window.location.reload(); }) .catch((err) => { console.log(err); }); } handleEditClickOpen(data) { this.setState({ title: data.todo.title, body: data.todo.body, todoId: data.todo.todoId, buttonType: 'Edit', open: true }); } handleViewOpen(data) { this.setState({ title: data.todo.title, body: data.todo.body, viewOpen: true }); } render() { const DialogTitle = withStyles(styles)((props) => { const { children, classes, onClose, ...other } = props; return (  {children} {onClose ? (    ) : null}  ); }); const DialogContent = withStyles((theme) => ({ viewRoot: { padding: theme.spacing(2) } }))(MuiDialogContent); dayjs.extend(relativeTime); const { classes } = this.props; const { open, errors, viewOpen } = this.state; const handleClickOpen = () => { this.setState({ todoId: '', title: '', body: '', buttonType: '', open: true }); }; const handleSubmit = (event) => { authMiddleWare(this.props.history); event.preventDefault(); const userTodo = { title: this.state.title, body: this.state.body }; let options = {}; if (this.state.buttonType === 'Edit') { options = { url: `/todo/${this.state.todoId}`, method: 'put', data: userTodo }; } else { options = { url: '/todo', method: 'post', data: userTodo }; } const authToken = localStorage.getItem('AuthToken'); axios.defaults.headers.common = { Authorization: `${authToken}` }; axios(options) .then(() => { this.setState({ open: false }); window.location.reload(); }) .catch((error) => { this.setState({ open: true, errors: error.response.data }); console.log(error); }); }; const handleViewClose = () => { this.setState({ viewOpen: false }); }; const handleClose = (event) => { this.setState({ open: false }); }; if (this.state.uiLoading === true) { return ( {this.state.uiLoading && }  ); } else { return ( {this.state.buttonType === 'Edit' ? 'Edit Todo' : 'Create a new Todo'}   {this.state.buttonType === 'Edit' ? 'Save' : 'Submit'}                {this.state.todos.map((todo) => (     {todo.title}   {dayjs(todo.createdAt).fromNow()}   {`${todo.body.substring(0, 65)}`}     this.handleViewOpen({ todo })}> {' '} View{' '}   this.handleEditClickOpen({ todo })}> Edit   this.deleteTodoHandler({ todo })}> Delete     ))}    {this.state.title}       ); } } }

Šio failo pabaigoje pridėkite šį eksportą:

export default withStyles(styles)(todo); 

Pirmiausia suprasime, kaip veikia mūsų vartotojo sąsaja, o po to suprasime kodą. Eikite į naršyklę ir gausite šią vartotojo sąsają:

Apatiniame dešiniajame kampe spustelėkite mygtuką Pridėti ir gausite šį ekraną:

Pridėkite „Todo“ pavadinimą ir išsamią informaciją ir paspauskite mygtuką „Pateikti“. Gausite šį ekraną:

Po šio spustelėjimo rodinio mygtuko galėsite pamatyti visą „Todo“ informaciją:

Spustelėkite mygtuką Redaguoti ir galėsite redaguoti užduotį:

Spustelėkite mygtuką „Ištrinti“ ir galėsite ištrinti „Todo“. Žinodami, kaip veikia informacijos suvestinė, suprasime joje naudojamus komponentus.

1. Pridėti „Todo“: Norėdami įgyvendinti „add todo“, naudosime materialiosios vartotojo sąsajos komponentą „Dialogas“. Šis komponentas įgyvendina kablio funkcionalumą. Mes naudojame klases, todėl pašalinsime šią funkciją.

// This sets the state to open and buttonType flag to add: const handleClickOpen = () => { this.setState({ todoId: '', title: '', body: '', buttonType: '', open: true }); }; // This sets the state to close: const handleClose = (event) => { this.setState({ open: false }); };

Be to, mes taip pat pakeisime mygtuko „Pridėti Todo“ vietą.

// Position our button floatingButton: { position: 'fixed', bottom: 0, right: 0 }, 

Dabar sąrašo žymą pakeisime forma šiame dialoge. Tai padės mums pridėti naują dalyką.

// Show Edit or Save depending on buttonType state {this.state.buttonType === 'Edit' ? 'Save' : 'Submit'} // Our Form to add a todo    // TextField here   // TextField here   

TherankenaPateiktisusideda iš logikos skaityti buttonTypebūseną. Jei būsena yra tuščia eilutė, (“”)ji bus paskelbta „Add Todo“ API. Jei būsena yra Edittada pagal šį scenarijų, ji atnaujins redagavimo funkciją.

2. Gaukite „Todos“: norėdami parodyti užduotis, kurias naudosime, Grid containerir joje uždėsime Grid item. Viduje mes naudosime Cardkomponentą duomenims rodyti.

 {this.state.todos.map((todo) => (    // Here will show Todo with view, edit and delete button   ))} 

Žemėlapį naudojame tam, kad rodytume tikrąjį elementą, nes API juos siunčia į sąrašą. Norėdami gauti ir nustatyti būseną prieš pateikimą, naudosime „komponentWillMount“ gyvavimo ciklą. Yra 3 mygtukai ( žiūrėti, redaguoti ir ištrinti ), todėl mums reikės 3 tvarkytojų, kurie atliktų operaciją spustelėjus mygtuką. Apie šiuos mygtukus sužinosime atitinkamuose jų poskyriuose.

3. Redaguoti „Todo“: norint redaguoti Todo, mes pakartotinai naudojame dialogo langą, kuris naudojamas įtraukiant „Todo“. Norėdami atskirti mygtuko paspaudimus, mes naudojame buttonTypebūseną. „Add Todo“   buttonTypebūsena yra, (“”)o redaguoti - tai Edit.

handleEditClickOpen(data) { this.setState({ .., buttonType: 'Edit', .. }); }

Pagal handleSubmitmetodą mes perskaitome buttonTypebūseną ir tada atitinkamai išsiunčiame užklausą.

4. Ištrinti „Todo“: Spustelėjus šį mygtuką, mes išsiunčiame Todo objektą mūsų „deleteTodoHandler“ ir tada jis siunčia užklausą toliau į antrinę programą.

 this.deleteTodoHandler({ todo })}>Delete

5. Žiūrėti „Todo“: rodydami duomenis mes juos sutrumpinome, kad vartotojas galėtų pamatyti, kas yra „todo“. Bet jei vartotojas nori apie tai sužinoti daugiau, jis turi spustelėti rodinio mygtuką.

Tam naudosime dialogą „Individualizuotas“. Viduje mes naudojame DialogTitle ir DialogContent. Tai rodo mūsų pavadinimą ir turinį. „DialougeContent“ naudosime formą vartotojui paskelbtam turiniui rodyti. (Tai yra vienas sprendimas, kurį radau daug, ir jūs galite laisvai išbandyti kitą.)

// This is used to remove the underline of the Form InputProps={{ disableUnderline: true }} // This is used so that user cannot edit the data readonly

6. Taikymas tema: Tai yra paskutinis mūsų programos žingsnis. Taikysime temą savo programoje. Tam mes naudojame createMuiThemeir ThemeProvideriš materialiosios vartotojo sąsajos. Nukopijuokite ir įklijuokite šį kodą App.js:

import { ThemeProvider as MuiThemeProvider } from '@material-ui/core/styles'; import createMuiTheme from '@material-ui/core/styles/createMuiTheme'; const theme = createMuiTheme({ palette: { primary: { light: '#33c9dc', main: '#FF5722', dark: '#d50000', contrastText: '#fff' } } }); function App() { return (  // Router and switch will be here.  ); }

Mes praleido taikant tema mūsų mygtuką todo.jsį CardActions. Pridėkite rodinio, redagavimo ir ištrinimo mygtuko spalvų žymą.

Eikite į naršyklę ir pamatysite, kad viskas yra vienoda, išskyrus tai, kad programa yra kitos spalvos.

Ir mes baigėme! Mes sukūrėme „TodoApp“ naudodami „ReactJS“ ir „Firebase“. Jei viską sukūrėte iki šio taško, tada labai sveikinu jus su šiuo pasiekimu.

Nedvejodami susisiekite su manimi „Twitter“ ir „Github“.