{"data":{"allStrapiArticles":{"edges":[{"node":{"title":"Metoda mockup'u - mój sposób na pisanie czystszego kodu.","content":"Jest wiele zasad, które pomagają nam pisać czystszy i bardziej skalowalny kod (SOLID, KISS, DRY, YAGNI i tak dalej) ale niedawno wymyśliłem własną metodę, która umożliwia mi mieć kod bardziej pod kontrolą. Możliwe, że ta metoda działa tylko w moich przypadkach ale chciałbym podzielić się nią, ponieważ może zainspiruję Cię nieco do eksperymentowania na własnym przykładzie. Sposób ten polega na pisaniu na początku wysoko poziomowego kodu (poprzez zrozbienie mockup'u), a następnie zamykanie poszczególnych zadań i niższych poziomów abstracji w kolejnych plikach, metodach, w zależności od Twojej architektury.\n\nAby wytłumaczyć dokładniej co mam na myśli, nadajmy sobie jakiś kontekst: chciałbym dodać nową funcjonalność do mojej super oryginalnej aplikacji to-do 🤭. Na przykład, chciałbym pobrać informacje o notatkach z bazy danych i wykonać na nich parę operacji takich jak sortowanie, filtrowanie i modyfikowanie. Aby było prościej, to są dane, na których będziemy pracować:\n\n```\n[{ title: \"buy a milk\", completed: false }, \n  { title: \"feed the dog\", completed: true }, \n  { title: \"go for a walk\", completed: false }, \n  { title: \"design a layout\", completed: true }, \n  { title: \"do an English lesson\", completed: true }] \n```\n \nJeżeli nie jesteś zaznajomiony z podstawowymi zasadami pisania czystego kodu takich jak zasada jednej odpowiedzialności (single responsibility principle) Twoje rozwiązanie może wygląda mniej więcej tak:\n\n \n```\nfunction getAndProcesssTodos() { \n    const data = fetchFromSomewhere(); \n    const sortedData = data.sort((a, b) => a.title > b.title ? 1 : -1) \n    const filteredData = sortedData.filter(data => data.completed === true); \n\n    for (let i = 0; i < filteredData.length; i++) { \n        filteredData[i].title = filteredData[i].title.toUpperCase();\n        filteredData[i].title = `completed: ${filteredData[i].title}`;  \n    } \n\n    const modifiedData = filteredData.map(item => ({...item, title: item.title.toUpperCase()}))  \n    return modifiedData; \n\n} \n\nconsole.log(getAndProcesssTodos()) \n\n [{ title: 'COMPLETED: DESIGN A LAYOUT', completed: true },  \n  { title: 'COMPLETED: DO AN ENGLISH LESSON', completed: true },  \n  { title: 'COMPLETED: FEED THE DOG', completed: true } ] \n\n```\n\nJak widzisz, ten kod ma parę problemów. Nie jest reużywalny, trudny w utrzymaniu i debugowaniu, ponieważ nie zaplanowaliśmy wcześniej naszego planu działania. Zamiast pisać kolejne bazgroły, zatrzymajmy się na chwilę i zastanówmy się, jakie kroki musimy wykonać, aby ukończyć nasze zadanie pomyślnie.\n\n- Pobierz zadania\n- Posortuj\n- Filtruj\n- Oznacz jakoś ukończone zadania\n- Modifikuj\n- Wzróć rezultat\n\nTrzymajmy się naszego planu i twórzmy mockup naszej funkcji bez wchodzenia w szczegóły.\n\n```\nfunction getTodos() { \n  const todos = fetchTodos();\n  const sortedTodos = sortTodos(todos);\n  const filteredTodos = filterTodos(sortedTodos);\n  const modyfiedTodos = modifyTodos(filteredTodos);\n\n  return modifiedTodos;\n} \n```\n\nNa tym etapie nie skupiam się na tym jak te funkcje dokładnie wyglądają. Zamiast tego robię mockup **jak chciałbym aby wyglądał mój kod.** Teraz widzimy, że nasz kod jest podzielony na poszczególne odpowiedzialności, jest łatwiejszy i utrzymaniu i debugowaniu i nawet wygląda jak byśmy chceli. Również zmieniłem nazwy funkcji by określić, co dokładnie robią. Teraz możemy zaimplementować te funkcje.\n\nAle spójrzmy on tę funkcje raz jeszcze. Widzimy niepotrzebną redundancję w nazwach:  fetchTodos, sortTodos, filteredTodos. Wszędzie są todos! To sugeruje, aby rozwiązać ten problem w jakiś sposób. Możemy na przykład zamknąć nasze funkcje w klasie i tak zarządzać naszymi zadaniami. To brzmi jak dobry plan. Zrobimy klasę todos, i pozbędziemy się 'Todos' w nazwie każdej metody. Zobaczmy, jak możemy to osiągnąć z klasami ES6.\n\n```\nclass Todos { \n    constructor(todos) { \n        this.todos = todos; \n    } \n    get() { \n        return this.todos; \n    } \n    sort() { \n        this.todos = this.todos.sort((a, b) => a.title > b.title ? 1 : -1) \n        return this; \n    } \n    filter() { \n        this.todos = this.todos.filter(todo => todo.completed); \n        return this; \n    } \n    markCompleted() { \n        this.todos = this.todos.map(todo => ({ ...todo, title: `completed: ${todo.title}` })); \n        return this; \n    } \n    upperCaseTodos() { \n        this.todos = this.todos.map(todo => ({...todo, title: todo.title.toUpperCase()})); \n        return this; \n    } \n} \n \n\nconst todos = new Todos([ \n  { title: \"buy a milk\", completed: false }, \n  { title: \"feed the dog\", completed: true }, \n  { title: \"go for a walk\", completed: false }, \n  { title: \"design a layout\", completed: true }, \n  { title: \"do an English lesson\", completed: true }, \n]); \n \nconsole.log(todos\n    .filter() \n    .markCompleted() \n    .upperCaseTodos() \n    .sort() \n    .get()); \n\n\n[ { title: 'COMPLETED: DESIGN A LAYOUT', completed: true },  \n  { title: 'COMPLETED: DO AN ENGLISH LESSON', completed: true },  \n  { title: 'COMPLETED: FEED THE DOG', completed: true } ]  \n```\n\nTeraz możesz zauważyć jak wiele benefitów zyskaliśmy tylko poprzez zrobienie prostej listy kroków i mockup'u z odpowiednimi nazwami zmiennych. Mogliśmy dzięki temu znależć problem i zaproponować rozwiązanie. W dodatku, korzytając z chainingu możemy dowolnie łączyć nasze metody and wywoływać je w różnej kolejności co daje nam większą elastyczność. Oczywiście, przy bardziej skomplikowanych zadaniach możemy ponownie zasosować tę metodę, rozbić zadania na mniejsze i zamockować kod. Ten sposób pisania kodu pomaga mi właśnie w rozdzielaniu dużych problemów na mniejsze i budowania ich krok po kroku.","date":"2021-06-24","slug":"metoda-mockupu-moj-sposob-na-pisanie-czystszego-kodu","image":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAQL/xAAVAQEBAAAAAAAAAAAAAAAAAAABAP/aAAwDAQACEAMQAAABb2XTFU7C/8QAHBAAAgEFAQAAAAAAAAAAAAAAAQIAAwQREiEx/9oACAEBAAEFAtgCTFqHFr1ovn//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAZEAACAwEAAAAAAAAAAAAAAAAQEQABMXH/2gAIAQEABj8CTGOX0//EABoQAQADAAMAAAAAAAAAAAAAAAEAETEQUeH/2gAIAQEAAT8hpKBcJQTSfRImy34jjwf/2gAMAwEAAgADAAAAEKM//8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERYf/aAAgBAwEBPxBqFw//xAAXEQEBAQEAAAAAAAAAAAAAAAABABFR/9oACAECAQE/EBse3//EABsQAQACAwEBAAAAAAAAAAAAAAEAESFBYTFR/9oACAEBAAE/ELx2pyx3RMF+zP3bYdd7EJkOlbqMrPkaKnbP/9k=","aspectRatio":2,"src":"/static/cda132ca7a7fe23d16de0d530d797a8c/25a47/9efc245d491e265671a433c009720358.jpg","srcSet":"/static/cda132ca7a7fe23d16de0d530d797a8c/d77c5/9efc245d491e265671a433c009720358.jpg 600w,\n/static/cda132ca7a7fe23d16de0d530d797a8c/25a47/9efc245d491e265671a433c009720358.jpg 1000w,\n/static/cda132ca7a7fe23d16de0d530d797a8c/c66b0/9efc245d491e265671a433c009720358.jpg 1366w,\n/static/cda132ca7a7fe23d16de0d530d797a8c/f75ab/9efc245d491e265671a433c009720358.jpg 1920w,\n/static/cda132ca7a7fe23d16de0d530d797a8c/e2687/9efc245d491e265671a433c009720358.jpg 2560w,\n/static/cda132ca7a7fe23d16de0d530d797a8c/83a96/9efc245d491e265671a433c009720358.jpg 5029w","sizes":"(max-width: 1000px) 100vw, 1000px"}}},"categories":[{"name":"other"}]}},{"node":{"title":"The mockup method – my way to write cleaner code. ","content":"There are many principles that help us to write cleaner and more scalable code (SOLID, KISS, DRY, YAGNI and so on), but recently, I’ve work up my method that enables to have a code more under control. Maybe that method works only in my use cases but I would like to share it with you because it may inspire you to experiment with it a bit. This method consists in writing high-level code (by creating a start mockup) and closing the next levels of abstraction in the next files, methods, whatsoever depends on your architecture. \n\nIn order to thoroughly explain you my way of thinking, let’s have some context:  I would like to add a new feature to my super original to-do app 🤭. For example, I want to get all the notes from the database and do couple of operations like sorting, filtering and modifying the result. To keep it simple, these are the data we’ll be working with: \n\n```\n[{ title: \"buy a milk\", completed: false }, \n  { title: \"feed the dog\", completed: true }, \n  { title: \"go for a walk\", completed: false }, \n  { title: \"design a layout\", completed: true }, \n  { title: \"do an English lesson\", completed: true }] \n```\n \nSo, if you are not familiar with basic clean code principles like SRP (single responsibility principle) your solution can look something like that: \n\n \n```\nfunction getAndProcesssTodos() { \n    const data = fetchFromSomewhere(); \n    const sortedData = data.sort((a, b) => a.title > b.title ? 1 : -1) \n    const filteredData = sortedData.filter(data => data.completed === true); \n\n    for (let i = 0; i < filteredData.length; i++) { \n        filteredData[i].title = filteredData[i].title.toUpperCase(); \n        filteredData[i].title = `completed: ${filteredData[i].title}`;  \n    } \n\n    const modifiedData = filteredData.map(item => ({...item, title: item.title.toUpperCase()}))  \n    return modifiedData; \n\n} \n \n\nconsole.log(getAndProcesssTodos()) \n\n [{ title: 'COMPLETED: DESIGN A LAYOUT', completed: true },  \n  { title: 'COMPLETED: DO AN ENGLISH LESSON', completed: true },  \n  { title: 'COMPLETED: FEED THE DOG', completed: true } ] \n\n```\n\nAs you can see, this code has a few problems. It is not reusable, hard to maintain and debug, because we didn’t plan our way to solve the problem. Instead of writing code like that, let’s stop for a moment and wonder what steps do we need to complete this task successfully. Let’s create a list of activities step-by-step: \n\n- Fetch the todos\n- Sort\n- Filter\n- Mark completed tasks in some way\n- Modify\n- Return the result \n\nLet’s stick to our plan and create a mockup of our function without going into great detail.  \n\n```\nfunction getTodos() { \n  const todos = fetchTodos();\n  const sortedTodos = sortTodos(todos);\n  const filteredTodos = filterTodos(sortedTodos);\n  const modyfiedTodos = modifyTodos(filteredTodos);\n\n  return modifiedTodos;\n\n} \n```\n\nIn this step, I’m not focusing on how these function looks like exactly. Instead, I’m doing a mockup regarding **how I want to my code looks like.** Now, we can see that our code is separated into single functionalities, is easy to maintain, debug and it even looks like we want to. I also rename the function to determine that it exactly does. We can now implement the functions. \n\nBut, let's take a look on this function once again. I can see variable naming redundancy. fetchTodos, sortTodos, filteredTodos. Todos are everywhere! It suggests to solve this issue in some way. We can for example create a class that will be managing our todos. That sounds like a good plan. Let’s see how it can be achieved using ES6 classes. \n\n```\nclass Todos { \n    constructor(todos) { \n        this.todos = todos; \n    } \n    get() { \n        return this.todos; \n    } \n    sort() { \n        this.todos = this.todos.sort((a, b) => a.title > b.title ? 1 : -1) \n        return this; \n    } \n    filter() { \n        this.todos = this.todos.filter(todo => todo.completed); \n        return this; \n    } \n    markCompleted() { \n        this.todos = this.todos.map(todo => ({ ...todo, title: `completed: ${todo.title}` })); \n        return this; \n    } \n    upperCaseTodos() { \n        this.todos = this.todos.map(todo => ({...todo, title: todo.title.toUpperCase()})); \n        return this; \n    }\n} \n \n\nconst todos = new Todos([ \n  { title: \"buy a milk\", completed: false }, \n  { title: \"feed the dog\", completed: true }, \n  { title: \"go for a walk\", completed: false }, \n  { title: \"design a layout\", completed: true }, \n  { title: \"do an English lesson\", completed: true }, \n]); \n \n\nconsole.log(todos \n    .filter() \n    .markCompleted() \n    .upperCaseTodos() \n    .sort() \n    .get()); \n\n[ { title: 'COMPLETED: DESIGN A LAYOUT', completed: true },  \n  { title: 'COMPLETED: DO AN ENGLISH LESSON', completed: true },  \n  { title: 'COMPLETED: FEED THE DOG', completed: true } ]  \n\n```\n\nYou can now spot how many benefits we gained only by making a simple step list and mockup with appropriate variables naming. We could spot the problem with our code and were able to put forwards the solution to this problem. In addition, we can combine our methods and call them in different order what gives us more flexibility. Of course, in the case of more complex operations, you can use this method again to make a list of steps and do a mockup for your code. This method of writing code also helps me to separate the big problem into smaller pieces and build them step-by-step. ","date":"2021-06-23","slug":"the-mockup-method-my-way-to-write-cleaner-code","image":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAQFAQL/xAAVAQEBAAAAAAAAAAAAAAAAAAABAP/aAAwDAQACEAMQAAABb2XTFU7C/8QAHBAAAgEFAQAAAAAAAAAAAAAAAQIAAwQREiEx/9oACAEBAAEFAtgCTFqHFr1ovn//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAECAQE/AT//xAAZEAACAwEAAAAAAAAAAAAAAAAQEQABMXH/2gAIAQEABj8CTGOX0//EABoQAQADAAMAAAAAAAAAAAAAAAEAETEQUeH/2gAIAQEAAT8hpKBcJQTSfRImy34jjwf/2gAMAwEAAgADAAAAEKM//8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERYf/aAAgBAwEBPxBqFw//xAAXEQEBAQEAAAAAAAAAAAAAAAABABFR/9oACAECAQE/EBse3//EABsQAQACAwEBAAAAAAAAAAAAAAEAESFBYTFR/9oACAEBAAE/ELx2pyx3RMF+zP3bYdd7EJkOlbqMrPkaKnbP/9k=","aspectRatio":2,"src":"/static/cda132ca7a7fe23d16de0d530d797a8c/25a47/9efc245d491e265671a433c009720358.jpg","srcSet":"/static/cda132ca7a7fe23d16de0d530d797a8c/d77c5/9efc245d491e265671a433c009720358.jpg 600w,\n/static/cda132ca7a7fe23d16de0d530d797a8c/25a47/9efc245d491e265671a433c009720358.jpg 1000w,\n/static/cda132ca7a7fe23d16de0d530d797a8c/c66b0/9efc245d491e265671a433c009720358.jpg 1366w,\n/static/cda132ca7a7fe23d16de0d530d797a8c/f75ab/9efc245d491e265671a433c009720358.jpg 1920w,\n/static/cda132ca7a7fe23d16de0d530d797a8c/e2687/9efc245d491e265671a433c009720358.jpg 2560w,\n/static/cda132ca7a7fe23d16de0d530d797a8c/83a96/9efc245d491e265671a433c009720358.jpg 5029w","sizes":"(max-width: 1000px) 100vw, 1000px"}}},"categories":[{"name":"other"}]}},{"node":{"title":"Dlaczego nie musisz perfekcyjnie znać ES6+ przed nauką Reacta?","content":"Wiele osób mówi, że <i>musisz świetnie znać vanilla Javascript zanim zaczniesz naukę frameworka!</i> Przede wszystkim - NIE – nie musisz. Opiszę Ci mój start z Reactem i mój stan wiedzy jeżeli chodzi o Javascript.\n\nZanim przestaniesz czytać ten artykuł z bananem na twarzy i myślą, że możesz zaczynać bez podstawowej wiedzy muszę Cię zasmucić - niestety, ale powinieneś wiedzieć i być świadomym jednej rzeczy. Niektóre elementy ES6 to fundamenty składni współczesnego Javascriptu a ich nieznajomość może przynieść Ci zły start.\n\n**Co umiałem zanim zacząłem naukę Reacta?** \n\n- Dobre zrozumienie HTML i CSS\n- Flexbox i SCSS\n- Podstawy Node.js: Express.js, komendy NPM, workflow z Gulp i podstawy GIT\n- Świadomość rzeczy takich jak: hoisting, domknięcia i zasięg\n- Zrobiłem również kilka stron w HTML, CSS i vanilla JS takich jak aplikacja pogodowa czy to-do lista\n\nOczywiście nie musisz uczyć się Expressa, Gulka i wszystkich komend NPM aby zacząć naukę. Poznałem te rzeczy ponieważ chciałem je poznać tak czy siak. Wtedy zaczałem polepszać moją znajomość JS ze składnią ES6+. Po około trzech miesiącach zdecydowałem się na naukę React znając tylko podstawy ES6+. **Co rozumiem poprzez podstawy?**\n\n- Słowa kluczowe let i const, dlaczego nie używać var, dlaczego możemy modyfikować obiekty i tablicę pomimo stosowania const itd.\n- Template strings zamiast konkatenacji\n- Operatora rest i spread\n- Metody na tablicach (forEach, map, filter, reduce, sort, findIndex, some, any) i koncept funkcji wyższego rzędu\n- Funkcje strzałkowe\n- Obietnice i asynchroniczny JS ze składnią async/await\n- Klasy ES6 (tylko teoria)\n- Desktrukturyzacja obiektów i tablic (tylko teoria)\n\nI to wszystko. Nie znałem takich rzeczy jak moduły ES6, symbole, iteratory, struktury Set i Map czy Proxy. Poza modułami ES6, żadne z tych rzeczy nie występują w naturalnym środowisku Reacta (a jeżeli tak jest to zdecydowanie rzadziej). Nie umiałem wykorzystać klas i desktrukturyzacji w praktyce. Wiedziałem tylko, że takie coś istnieje. Może dla wielu z was wydaje się to dużo nauki, ale w rzeczywistości tak nie jest. Da się to ogarnąć całkiem szybko ale rzeczy te są absolutnym must-have jeżeli chodzi o start z nauką nowej biblioteki. Dlaczego?\n\nOtóż komponenty funkcyjne, hooki czy context API stoją u podstaw Reacta w 2021 roku. Oznacza to, że musisz wiedzieć jak desktrukturyzować propsy w funkcjach strzałkowych, rozumieć składnię hooków jak np. useState, korzystać z domyślnych i nazywanych exportów i importów, jak iterować po tablicach korzystając z różnych metod i tak dalej. W dodatku, różne biblioteki z ekosystemu Reacta używają ciekawych funkcji ES6. Na przykład GraphQL korzysta z template strings, a Redux-saga wykorzystuje potencjał generatorów. To kolejny argument za tym, dlaczego nie powinieneś przejmować się wszystkimi ficzerami ES6 zanim wskoczysz w bardziej kompleksowe biblioteki, co więcej:\n\n\"ucz się nowych rzeczy tylko wtedy, kiedy to konieczne na przykład, gdy chcesz poznać nową technologię. Inna wiedza - bez jej praktykowania - wyleci z Twojej głowy szybciej niż myślisz\"\n\nModuły ES6, klasy, metoda bind, konfiguracja Webpacka, narzędzia jak Prettier, ESLint Map, Set - wszystkich tych rzeczy nauczyłem się tylko podczas nauki i praktykowania, co dodatkowo dało mi wiele zabawy i nie załuję mojej decyzji.\n\nWięc moja wskazówka dla Ciebie to: wyluzuj, nie ucz się przesadnie każdego detalu ES6 ponieważ istnieje prawdopodobieństwo, że zapomnisz o tym bez praktycznego wykorzystania w praktycznych przykładach z życia wziętych. Naucz się fundamentów, które wymieniłem wyżej. Jeżeli nie będziesz w stanie zrozumieć konkretnych konceptów i idei w React, zatrzymaj się na moment i wróć do tego ponownie za jakiś czas. Właśnie tak wygląda proces nauki programowania 😊. Trzymam za Ciebie kciuki!\n\nNarazie! ✌️ \n     ","date":"2021-06-05","slug":"dlaczego-nie-musisz-perfekcyjnie-znać-es6-przed-nauka-reacta","image":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAC/9oADAMBAAIQAxAAAAHj3MJVpFv/xAAbEAACAwADAAAAAAAAAAAAAAABAgADEQQSMf/aAAgBAQABBQJVLSvj6G6iUnKQYff/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAWEQEBAQAAAAAAAAAAAAAAAAAAEUH/2gAIAQIBAT8B1X//xAAZEAACAwEAAAAAAAAAAAAAAAAAARARIVH/2gAIAQEABj8CwtspJGdHH//EABoQAQACAwEAAAAAAAAAAAAAAAEAESExcUH/2gAIAQEAAT8hYoKxKEFwOaHsRbJnrkT07iyn/9oADAMBAAIAAwAAABBYD//EABURAQEAAAAAAAAAAAAAAAAAABEA/9oACAEDAQE/EFi//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAx/9oACAECAQE/EBxH/8QAHBABAAIDAAMAAAAAAAAAAAAAAQARITFBUWHR/9oACAEBAAE/ECHjoLibG6ht78ZWZBvG3tjcq2qriJSsU7E3u5//2Q==","aspectRatio":2,"src":"/static/49952011adc2d6ef20ab0001e87e93f7/25a47/e2704ee865daf2fee3128ec29a1823c7.jpg","srcSet":"/static/49952011adc2d6ef20ab0001e87e93f7/d77c5/e2704ee865daf2fee3128ec29a1823c7.jpg 600w,\n/static/49952011adc2d6ef20ab0001e87e93f7/25a47/e2704ee865daf2fee3128ec29a1823c7.jpg 1000w,\n/static/49952011adc2d6ef20ab0001e87e93f7/c66b0/e2704ee865daf2fee3128ec29a1823c7.jpg 1366w,\n/static/49952011adc2d6ef20ab0001e87e93f7/9ef11/e2704ee865daf2fee3128ec29a1823c7.jpg 1565w","sizes":"(max-width: 1000px) 100vw, 1000px"}}},"categories":[{"name":"frontend"},{"name":"other"}]}},{"node":{"title":"Why you don’t have to know ES6+ perfectly before learning React? ","content":"A lot of people say: <i>you have to know JavaScript inside out before you start learning framework!</i> First of all, NO – you don't have to. I will describe my start with React and what was the state of my knowledge when it comes to JavaScript.\n\nBefore you stop reading this article with a smile and the thought that you can start learning now even without basic knowledge, I have to stop you and inform that unfortunately, you should know of a few things. Some ES6 features are the cornerstone of the modern JavaScript syntax and lack of consciousness of them might bring you bad start, right? \n\n**So, what I knew before I started learning React?** \n\n- Good HTML and CSS understanding\n- Flexbox and SCSS\n- Node.js basics: Express.js, NPM commands, Gulp workflow and GIT basics\n- Awareness of terms like: hoisting, closure and scope\n- I’ve also made a few websites using HTML, CSS and vanilla JS like weather app and to-do list\n\n\nOf course, you don't need to learn Express, Gulp, all NPM commands in order to start your learning. I got to know these things because I had been wanted to learn them one way or another. Then, I started improving my JS with ES6+ syntax. About three months later, when I ultimately decided to learn React, I know only basics of ES6+. **What I mean writing basics?** Here you are: \n\n- Let, const keywords, why not to use var and why we can modify objects and arrays despite using the const keyword\n- Template string instead of concatenating\n- Rest and spread operator\n- Array methods (forEach, map, filter, reduce, sort, findIndex, some, any) and a concept of higher order functions \n- Arrow functions\n- Promises and asynchronous JS with async/await. (also callbacks and promises)\n- Classes (only theoretical knowledge)\n- Array and objects destructuring (only theoretical knowledge)\n\nAnd that’s all, nothing more. I didn't know ES6 modules, symbols, iterators, Maps and Sets, or Proxy. Why? Because except for ES6 modules these things almost never occur in natural React habitat. Also, I lack the practical use of destructuring and classes. Of course, I know of them but the only thing I didn't have was the practice. It could be a lot of things to learn for some of you but it's not. These things are the must-have before you think of learning this library. Why? \n\nSo, in 2021 functional components, hooks and context API underlies the world of React. It means you must know how to destructure props in arrow functions, syntax of different hooks like useState, default and named exports, imports, how to list through arrays using array methods and so on. In addition, different React libraries like to make good use of some ES6 features, for instance GraphQL or Styled-components use template strings mechanism and Redux-saga uses generators. So that’s the next argument about why you don't need to worry about all ES6 features before you jump into more complex libraries, all the more:\n\n\"learn new things only when it's necessary because, for example, you want to get to know new technology. Other knowledge - without practicing - is bound to leave your mind faster than you might think.\"\n\nES6 modules, classes, bind method, webpack configuration, prettier, ESList, Maps and Sets - I get to know these things only during the learning process which additionally gave me a lot of fun and I don't regret my decision at all. \n\nSo, my tip for you is: hold for horses, don't learn exaggeratingly every detail of ES6 because there is a possibility that you will forget about them without practical use and true-life examples. Get to know the core concepts that I named above and don't worry. If you won’t be able to understand specific parts of React, stop and back to the vanilla JS for a moment and try again. That's exactly how the learning process in programming looks like 😊 I'm keeping my fingers crossed for you!  \n\nCya! ✌️ \n     ","date":"2021-06-04","slug":"why-you-dont-have-to-know-es6-perfectly-before-learning-react","image":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQDBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAC/9oADAMBAAIQAxAAAAHj3MJVpFv/xAAbEAACAwADAAAAAAAAAAAAAAABAgADEQQSMf/aAAgBAQABBQJVLSvj6G6iUnKQYff/xAAUEQEAAAAAAAAAAAAAAAAAAAAQ/9oACAEDAQE/AT//xAAWEQEBAQAAAAAAAAAAAAAAAAAAEUH/2gAIAQIBAT8B1X//xAAZEAACAwEAAAAAAAAAAAAAAAAAARARIVH/2gAIAQEABj8CwtspJGdHH//EABoQAQACAwEAAAAAAAAAAAAAAAEAESExcUH/2gAIAQEAAT8hYoKxKEFwOaHsRbJnrkT07iyn/9oADAMBAAIAAwAAABBYD//EABURAQEAAAAAAAAAAAAAAAAAABEA/9oACAEDAQE/EFi//8QAFhEBAQEAAAAAAAAAAAAAAAAAARAx/9oACAECAQE/EBxH/8QAHBABAAIDAAMAAAAAAAAAAAAAAQARITFBUWHR/9oACAEBAAE/ECHjoLibG6ht78ZWZBvG3tjcq2qriJSsU7E3u5//2Q==","aspectRatio":2,"src":"/static/49952011adc2d6ef20ab0001e87e93f7/25a47/e2704ee865daf2fee3128ec29a1823c7.jpg","srcSet":"/static/49952011adc2d6ef20ab0001e87e93f7/d77c5/e2704ee865daf2fee3128ec29a1823c7.jpg 600w,\n/static/49952011adc2d6ef20ab0001e87e93f7/25a47/e2704ee865daf2fee3128ec29a1823c7.jpg 1000w,\n/static/49952011adc2d6ef20ab0001e87e93f7/c66b0/e2704ee865daf2fee3128ec29a1823c7.jpg 1366w,\n/static/49952011adc2d6ef20ab0001e87e93f7/9ef11/e2704ee865daf2fee3128ec29a1823c7.jpg 1565w","sizes":"(max-width: 1000px) 100vw, 1000px"}}},"categories":[{"name":"other"},{"name":"frontend"}]}},{"node":{"title":"Komunikacja frontend-backend w React, Express i REST API - moje podejście.","content":"W świecie Javascriptu istnieje mnóstwo frameworków i bibliotek do budowania aplikacji webowych. Najpopularniejszą technologią na frontendzie jest React, a po stronie serwera - Express, Koa czy Nest.js. Podczas budowania aplikacji fullstackowej ważne jest, aby zaplanować dobrze architekturę, strukturę katalogów i sposów przepływu danych w obrębie naszej aplikacji. W tym artykule przedstawię moje podejścia do problemu jakim jest komunikacja między tymi dwoma światami z użyciem tradycyjnego REST API.\n\nJako przykład, chciałbym przedstawić kilka części mojej aplikacji z quizami którą tworzyłem przez ostatnie miesiące. Kliknij, by przejść do projektu [tutaj](https://github.com/krzysztof01-sz/squizer-app-frontend)\n\n#### Dashboard\n\nW komponencie dashboard mamy listę z quizami stworzonymi przez użytkowników. Aby odczytać informacje o tych quizach musimy wykonać zapytanie do naszego API. Właśnie tutaj zaczyna się cała komunikacja.\n\nPrzejdź do => /src/pages/Dashboard/index.js \n\n```\nconst Dashboard = () => {\n  const { data: quizzes, loading, error } = useFetching(getQuizzes);\n\n  if (loading) return <Loader />;\n  if (error) return <ErrorPage msg={error} />;\n\n  return (\n    <Layout>\n...\n```\n\n#### API na frontendzie\n\nW linii drugiej wywołuje własny hook o nazwie useFetching z argumentem getQuizzes. Ten argument to referencja do funkcji w pliku /src/api.index.js. Zobaczmy jak ta funkcja wygląda a następnie pokażę co dzieje się w hooku useFetching.\n\n```\nexport const getQuizzes = async () => {\n  const { data } = await instance.get('/api/quizzes').catch(({ response }) => response);\n  return data;\n};\n```\n\nJest to zwykła asynchroniczna funkcja, która wysyła zapytanie do ścieżki /api/quizzes używając paczki axios. Używam również metody catch aby wyłapać potencjalne błędy. Wszystkie informacje znajdują się we właściwości data, więc destrukturyzuje je używając składni ES6. \n\n#### Hook useFetching\nPrzejdź do => /src/hooks/useFetching.js \n\n\n```\nexport const useFetching = (method, ...methodArgs) => {\n  const [loading, setLoading] = useState(true);\n  const [error, setError] = useState(null);\n  const [data, setData] = useState(undefined);\n\n  useEffect(() => {\n    const cancelToken = axios.CancelToken;\n    const source = cancelToken.source();\n\n    (async () => {\n      const { type, data, msg } = await method([...methodArgs]);\n\n      if (type === responseTypes.success) {\n        setData(data);\n      } else {\n        setError(msg);\n      }\n\n      setLoading(false);\n    })();\n\n    return () => source.cancel();\n  }, []);\n\n  return { data, loading, error };\n};\n```\n\nuseFetching to nic innego jak funkcja, która jako parametr przyjmuje referencję do funkcji, którą ma wywołać oraz tablicę opcjonalnych parametrów, które ta funkcja przyjmuje. Poniżej deklaruję stan (loading, error i data). W linii 10 wywołuję przekazaną jako parametr funkcję z argumentami używając spread operatora i wtedy desktrukturyzuję response, data i wiadomość z błędem (tutaj to wartość o nazwie msg). Potem, jeżeli zapytanie zakończyło się pomyślnie ustawiam zmienną data, error i wartość zmiennej loading na false aby dać znak, że żądanie się zakończyło, a komponent loader może zniknąć. Pod koniec zwracam obiekt z niezbędnymi danymi do wyświetlenia w komponencie. **Nie zapominaj by zakończyć wszyskie aktywne subskrypcje i zapytania asynchroniczne w funkcji czyszczącej komponent (cleanup function)**. Ja to robię używając accessTokena, który daje nam paczka axios. Teraz, wróćmy do naszego komponentu Dashboard.\n\n\n```\n  const { data: quizzes, loading, error } = useFetching(getQuizzes);\n```\n\nTutaj destrukturyzuję zwrócony obiekt z hooka, a następnie używam tych danych do zwizualizowania naszego stanu w UI.\n\n```\n  if (loading) return <Loader />;\n  if (error) return <ErrorPage msg={error} />;\n```\n\nI na końcu iterujemę po tablicy z quizami.\n\n#### Backend w Express\n\nPrzejdźmy teraz do backendu, aby zobaczyć w jaki sposób nasze zapytanie jest obsługiwane.\n\n[Backend tutaj, zapraszam](https://github.com/krzysztof01-sz/squizer-app-backend/ )\n\nPrzejdź do => /routes/api.js \n\n```\nrouter.get(\"/quizzes\", verify, quizzesController.getQuizzes);\n```\n\nW tej linii tworzę ścieżkę GET /quizzes która obsługuje zapytanie. Teraz zapytanie jest przekazywane do dedykowanego kontrolera.\n\n#### Kontroler\n\nRolą kontrolerów jest:\n\n<ul>\n<li>Przyjąć zapytanie</li>\n<li>Wywołać do pracy konkretny Service (jeżeli to konieczne)</li>\n<li>Zwrócić dane (lub błąd)</li>\n</ul>\n\nWłaśnie to dzieję się w pliku /controllers/quizzes.js.\n\n```\nmodule.exports.quizzesController = {\n  getQuizzes: async (req, res) => {\n    if (req.user) {\n      const { type, data, msg } = await QuizzesService.getQuizzes();\n\n      if (type === responseTypes.success) {\n        res.status(200).json({ type, data });\n      } else {\n        res.status(401).json({ type, msg });\n      }\n    }\n  },\n...\n```\n\nTutaj mamy metodę getQuizzes, która spełnia wyżej wymienione reguły:\n<ul>\n<li>Przyjmuje zapytanie (linia 2)</li>\n<li>Wywołuje odpowiedni Service (linia 4)</li>\n<li>Zwraca dane lub błąd w zależności od pola type (linie 6-10)</li>\n</ul>\nPierwsza i trzecia linia to kroki raczej trywialne. Najciekawsza rzecz dzieje się w linii 4, gdzie wywołujemy do pracy Service. \n\n#### Service\n\nRolą serwisów jest obsługa bardziej zaawansowanych i czasochłonnych zadań takich jak wykonywanie zapytań do bazy danych, wykonywanie obliczeń, czy przygotowywanie gotowego obiektu do odesłania kontrolerowi.\n\n```\nclass QuizzesService {\n  async getQuizzes() {\n    try {\n      const quizzes = await Quiz.find({}).sort({ creationDate: -1 });\n\n      if (quizzes.length > 0) {\n        return {\n          type: responseTypes.success,\n          data: quizzes,\n        };\n      } else throw messages.QUIZZES_NOT_FOUND;\n    } catch (e) {\n      return makeResponse(e, responseTypes.error);\n    }\n  }\n...\n```\n\nW ostatnim kroku, wykonuję zapytanie do MongoDB. Dostaję wszystkie quizy, i sortuję je według daty publikacji. Jeżeli quizy istnieją, zwraca je - w przeciwnym przypadku wyłapuję błąd i odsyłam odpowiedź.\n\nW tym miejscu polecam Ci używać składni try catch aby Twój kod był bardziej czytelny i łatwy do debugowania.\n\nVoila! Nasza komunikacja właśnie dobiegła końca. Teraz, dane zwrócone z Service'u odsyłamy kontrolerowi, a następinie na część frontendową. Następnie rozwiązywana zostaje funkcja w api, hooku useFetching i stamtąd trafia do odpowiedniego Reacowego komponentu, gdzie zaczęła się cała długa, ale fajna podróż! 😎 \n\nPodsumowując, tak wygląda komunikacja krok po kroku:\n\nKomponent Reactowy -> hook useFetching -> metoda w API -> ścieżka na backend -> kontroler -> Service (tutaj mamy nasze dane) -> kontroler -> metoda API -> hook useFetching -> komponent Reactowy (korzystamy z danych). \n\n ","date":"2021-06-02","slug":"komunikacja-frontend-backend-w-react-express-i-rest-api-moje-podejscie.","image":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAGxUyanYAH/xAAaEAACAgMAAAAAAAAAAAAAAAACAwAEEjND/9oACAEBAAEFAgZihbRMpwqbJ//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABoQAAEFAQAAAAAAAAAAAAAAAAEAAhARYXH/2gAIAQEABj8C0Kg2ofxCP//EAB0QAAICAQUAAAAAAAAAAAAAAAERACFRMUFhcbH/2gAIAQEAAT8hE8tAY3hydS33HiHSizufIhif/9oADAMBAAIAAwAAABD3H//EABYRAAMAAAAAAAAAAAAAAAAAABARIf/aAAgBAwEBPxB0f//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAECAQE/EIf/xAAbEAEAAwEBAQEAAAAAAAAAAAABABEhQTFhcf/aAAgBAQABPxAbd5UOasWhXbS24AFCgyN1ZuvtkbZLvr9QC8evJ//Z","aspectRatio":2,"src":"/static/f2d285ad9bd918792ad7f1507e74014a/25a47/659afd138585d7eff1b251d80ea20a22.jpg","srcSet":"/static/f2d285ad9bd918792ad7f1507e74014a/d77c5/659afd138585d7eff1b251d80ea20a22.jpg 600w,\n/static/f2d285ad9bd918792ad7f1507e74014a/25a47/659afd138585d7eff1b251d80ea20a22.jpg 1000w,\n/static/f2d285ad9bd918792ad7f1507e74014a/c66b0/659afd138585d7eff1b251d80ea20a22.jpg 1366w,\n/static/f2d285ad9bd918792ad7f1507e74014a/f75ab/659afd138585d7eff1b251d80ea20a22.jpg 1920w,\n/static/f2d285ad9bd918792ad7f1507e74014a/e2687/659afd138585d7eff1b251d80ea20a22.jpg 2560w,\n/static/f2d285ad9bd918792ad7f1507e74014a/efd47/659afd138585d7eff1b251d80ea20a22.jpg 3882w","sizes":"(max-width: 1000px) 100vw, 1000px"}}},"categories":[{"name":"frontend"},{"name":"backend"}]}},{"node":{"title":"How to cope with frontend-backend communication using React, Express and REST API? ","content":"In the world of Javascript, there are plenty of frameworks and libraries for building web applications. The most popular frontend technology is React and on the backend side - Express, Koa, or Nest.js. When building a full-stack app, it’s super important to plan the architecture, directory structure, and the way the data flow through a code. In this article, I’ll depict my solution to the problem of communication using the traditional REST API. \n\nAs an example, I would like to show different parts of my quiz application which I’ve been creating for the last months.  Click to go the project [here!](https://github.com/krzysztof01-sz/squizer-app-frontend)\n\n#### Dashboard component\n\nIn a dashboard component, we have a list of quizzes created by users. In order to get them from our database (MongoDB), we have to make a request to our API. That’s where the communication starts. \n\nGo here => /src/pages/Dashboard/index.js \n\n```\nconst Dashboard = () => {\n  const { data: quizzes, loading, error } = useFetching(getQuizzes);\n\n  if (loading) return <Loader />;\n  if (error) return <ErrorPage msg={error} />;\n\n  return (\n    <Layout>\n...\n```\n\n#### Frontend API\n\nIn line 2, I’m calling a custom hook (useFetching) with a getQuizzes argument. This argument is the reference to a function from the /src/api.index.js file. So let’s see how this function looks like and then, I’ll explain to you what happens in the useFetching hook. \n\n```\nexport const getQuizzes = async () => {\n  const { data } = await instance.get('/api/quizzes').catch(({ response }) => response);\n  return data;\n};\n```\n\nThis is a simple asynchronous function that sends a request to /api/quizzes using the axios package. I’m also using the catch method to gather potential errors. All the returned information is in a data property so I grab it using ES6 destructuring. \n\n#### Custom useFetching hook\n\nGo here => /src/hooks/useFetching.js \n\n\n```\nexport const useFetching = (method, ...methodArgs) => {\n  const [loading, setLoading] = useState(true);\n  const [error, setError] = useState(null);\n  const [data, setData] = useState(undefined);\n\n  useEffect(() => {\n    const cancelToken = axios.CancelToken;\n    const source = cancelToken.source();\n\n    (async () => {\n      const { type, data, msg } = await method([...methodArgs]);\n\n      if (type === responseTypes.success) {\n        setData(data);\n      } else {\n        setError(msg);\n      }\n\n      setLoading(false);\n    })();\n\n    return () => source.cancel();\n  }, []);\n\n  return { data, loading, error };\n};\n```\n\nThis function excepts the method to call and the array of the method arguments (if they exist). Below I declare state (loading, error, and data). In line 10, I’m calling the passed method with the potential arguments using the spread operator and then, destructuring the type of the response, data, and an error message (here it’s a msg value). After that, if the request finished successfully, I set the data, the error, and finally set the loading variable to false in order to inform that the request had been finished and a loader component can disappear. In the end, I return the object with all the necessary data. Don’t remember to close all subscriptions and asynchronous tasks in a cleanup function (here I’m using axios.CancelToken). Now, back to the first code snippet and look once again.\n\n\n```\n  const { data: quizzes, loading, error } = useFetching(getQuizzes);\n```\n\nHere, I’m destructuring the object returned from the hook and now, I can use that data to visualize the result: \n\n```\n  if (loading) return <Loader />;\n  if (error) return <ErrorPage msg={error} />;\n```\n\nAnd finally, list through the quizzes array. \n\n#### Express.js Backend\n\nNow, let’s head over to the backend to show how the request is processed there. \n\n[Backend here](https://github.com/krzysztof01-sz/squizer-app-backend/ )\n\nGo to => /routes/api.js \n\n```\nrouter.get(\"/quizzes\", verify, quizzesController.getQuizzes);\n```\n\nIn this line,  I created a GET /quizzes route that handles the request. This request is now forwarding to the dedicated quizzesController. Let’s take a look there. \n\n#### Controller\n\nThe role of the controller is to: \n\n<ul>\n<li>Obtain the request</li>\n<li>Call an appropriate service (if needed)</li>\n<li>Return a data or an error</li>\n</ul>\n\nAnd that’s what happens in a /controllers/quizzes.js file\n\n```\nmodule.exports.quizzesController = {\n  getQuizzes: async (req, res) => {\n    if (req.user) {\n      const { type, data, msg } = await QuizzesService.getQuizzes();\n\n      if (type === responseTypes.success) {\n        res.status(200).json({ type, data });\n      } else {\n        res.status(401).json({ type, msg });\n      }\n    }\n  },\n...\n```\n\nHere we have the getQuizzes method that meets the aforementioned requirements: \n<ul>\n<li>Obtain the request (line 2)</li>\n<li>Call an appropriate service (line 4)</li>\n<li>Return the data or error in according to thr returned type value (lines 6-</li>\n</ul>\nThe first and the third step is quite simple but the most interesting thing is in line 4. Here, I’m calling the quizzes service. \n\n#### Service\n\nThe role of the service is to handle more complex tasks, for instance, making database queries and preparing the data to pass to our controller. \n\n```\nclass QuizzesService {\n  async getQuizzes() {\n    try {\n      const quizzes = await Quiz.find({}).sort({ creationDate: -1 });\n\n      if (quizzes.length > 0) {\n        return {\n          type: responseTypes.success,\n          data: quizzes,\n        };\n      } else throw messages.QUIZZES_NOT_FOUND;\n    } catch (e) {\n      return makeResponse(e, responseTypes.error);\n    }\n  }\n...\n```\n\nIn the last step, I’m doing the query to MongoDB. I’m getting all quizzes, sorting them by the publish date. If the quizzes exist, I return them but if not, I catch an error and send them back. \n\nI recommend you to use try catch syntax to make the code more readable and easy to debug. \n\nVoila! The whole communication ends right here. Now, the data returned from this service are coming back to the controller, then to the frontend side (/src/api/index.js), next to the useFetching hook, and in the end to the appropriate React component (Dashboard) from which we’ve been started our long but cool trip! 😎 \n\nTo sum up, the communication step by step looks like this: \n\nReact component -> useFetching hook -> API method -> backend route -> controller -> service (we have the data) -> controller -> API method -> useFetching hook -> React component (we use the data). \n","date":"2021-06-01","slug":"how-to-cope-with-frontend-backend-communication-using-rest-api","image":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAGxUyanYAH/xAAaEAACAgMAAAAAAAAAAAAAAAACAwAEEjND/9oACAEBAAEFAgZihbRMpwqbJ//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABoQAAEFAQAAAAAAAAAAAAAAAAEAAhARYXH/2gAIAQEABj8C0Kg2ofxCP//EAB0QAAICAQUAAAAAAAAAAAAAAAERACFRMUFhcbH/2gAIAQEAAT8hE8tAY3hydS33HiHSizufIhif/9oADAMBAAIAAwAAABD3H//EABYRAAMAAAAAAAAAAAAAAAAAABARIf/aAAgBAwEBPxB0f//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAECAQE/EIf/xAAbEAEAAwEBAQEAAAAAAAAAAAABABEhQTFhcf/aAAgBAQABPxAbd5UOasWhXbS24AFCgyN1ZuvtkbZLvr9QC8evJ//Z","aspectRatio":2,"src":"/static/f2d285ad9bd918792ad7f1507e74014a/25a47/659afd138585d7eff1b251d80ea20a22.jpg","srcSet":"/static/f2d285ad9bd918792ad7f1507e74014a/d77c5/659afd138585d7eff1b251d80ea20a22.jpg 600w,\n/static/f2d285ad9bd918792ad7f1507e74014a/25a47/659afd138585d7eff1b251d80ea20a22.jpg 1000w,\n/static/f2d285ad9bd918792ad7f1507e74014a/c66b0/659afd138585d7eff1b251d80ea20a22.jpg 1366w,\n/static/f2d285ad9bd918792ad7f1507e74014a/f75ab/659afd138585d7eff1b251d80ea20a22.jpg 1920w,\n/static/f2d285ad9bd918792ad7f1507e74014a/e2687/659afd138585d7eff1b251d80ea20a22.jpg 2560w,\n/static/f2d285ad9bd918792ad7f1507e74014a/efd47/659afd138585d7eff1b251d80ea20a22.jpg 3882w","sizes":"(max-width: 1000px) 100vw, 1000px"}}},"categories":[{"name":"backend"},{"name":"frontend"}]}},{"node":{"title":"Hymn do testera Kuby","content":"# Testerze Kubo,\n\n&nbsp;\n&nbsp;\n\nWielkie Bóg zapłać za testowanie bloga mojej strony. Jestem wdzięczny\n&nbsp;\n\n🙏","date":"2021-01-26","slug":"hymn-do-testera","image":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAAC/9oADAMBAAIQAxAAAAFbD0iAm//EABoQAAICAwAAAAAAAAAAAAAAAAECAAMEEiL/2gAIAQEAAQUCBVhW2OTaVDxehYq7/wD/xAAVEQEBAAAAAAAAAAAAAAAAAAAQEf/aAAgBAwEBPwGH/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQIBAT8Bp//EAB0QAAICAQUAAAAAAAAAAAAAAAABAhESEBMhMXH/2gAIAQEABj8CTmrK28fR4xjWivk6R//EABsQAQADAAMBAAAAAAAAAAAAAAEAESFBkbHB/9oACAEBAAE/IdrFTBKJ2uSNI4IQUca2fatlp5T/2gAMAwEAAgADAAAAEKfP/8QAFREBAQAAAAAAAAAAAAAAAAAAAQD/2gAIAQMBAT8QQMBf/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAECAQE/EBJa3//EABwQAQEBAAMAAwAAAAAAAAAAAAERACFBUTGx8P/aAAgBAQABPxCnR4oHRry0FnD7w1PISPBrpkcIzE8P+riRP467/9k=","aspectRatio":2,"src":"/static/36c9fcfe497371f24c8f0805dbf88af0/25a47/e499ae19f130a5bb3e05a61694f888a3.jpg","srcSet":"/static/36c9fcfe497371f24c8f0805dbf88af0/d77c5/e499ae19f130a5bb3e05a61694f888a3.jpg 600w,\n/static/36c9fcfe497371f24c8f0805dbf88af0/25a47/e499ae19f130a5bb3e05a61694f888a3.jpg 1000w,\n/static/36c9fcfe497371f24c8f0805dbf88af0/c66b0/e499ae19f130a5bb3e05a61694f888a3.jpg 1366w,\n/static/36c9fcfe497371f24c8f0805dbf88af0/f75ab/e499ae19f130a5bb3e05a61694f888a3.jpg 1920w,\n/static/36c9fcfe497371f24c8f0805dbf88af0/e2687/e499ae19f130a5bb3e05a61694f888a3.jpg 2560w,\n/static/36c9fcfe497371f24c8f0805dbf88af0/900ba/e499ae19f130a5bb3e05a61694f888a3.jpg 3394w","sizes":"(max-width: 1000px) 100vw, 1000px"}}},"categories":[{"name":"other"}]}},{"node":{"title":"Hello world!","content":"# Heey!\n\n&nbsp;\n\nFinally, after 12 days of work, I'm writing my first post on this blog! 🤩 I've been creating it using Gatsby, Strapi, GraphQL, and Styled-components. These technologies made my curious and I felt that I must try them making some project. I also thought it's a good idea to start publishing my own articles with my experience that I'm reaping all the time. It's a common knowledge that there are million blogs about web development but because of my little laziness I'll be publishing short and very concise articles, quick in reading and full of content (I'm doing my best 😊). I'm also bending over backwards to keep your attention.\n\n&nbsp;  \n\n### See you later!","date":"2021-01-23","slug":"hello-world","image":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAMEBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAGxUyanYAH/xAAaEAACAgMAAAAAAAAAAAAAAAACAwAEEjND/9oACAEBAAEFAgZihbRMpwqbJ//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABoQAAEFAQAAAAAAAAAAAAAAAAEAAhARYXH/2gAIAQEABj8C0Kg2ofxCP//EAB0QAAICAQUAAAAAAAAAAAAAAAERACFRMUFhcbH/2gAIAQEAAT8hE8tAY3hydS33HiHSizufIhif/9oADAMBAAIAAwAAABD3H//EABYRAAMAAAAAAAAAAAAAAAAAABARIf/aAAgBAwEBPxB0f//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAECAQE/EIf/xAAbEAEAAwEBAQEAAAAAAAAAAAABABEhQTFhcf/aAAgBAQABPxAbd5UOasWhXbS24AFCgyN1ZuvtkbZLvr9QC8evJ//Z","aspectRatio":2,"src":"/static/f2d285ad9bd918792ad7f1507e74014a/25a47/659afd138585d7eff1b251d80ea20a22.jpg","srcSet":"/static/f2d285ad9bd918792ad7f1507e74014a/d77c5/659afd138585d7eff1b251d80ea20a22.jpg 600w,\n/static/f2d285ad9bd918792ad7f1507e74014a/25a47/659afd138585d7eff1b251d80ea20a22.jpg 1000w,\n/static/f2d285ad9bd918792ad7f1507e74014a/c66b0/659afd138585d7eff1b251d80ea20a22.jpg 1366w,\n/static/f2d285ad9bd918792ad7f1507e74014a/f75ab/659afd138585d7eff1b251d80ea20a22.jpg 1920w,\n/static/f2d285ad9bd918792ad7f1507e74014a/e2687/659afd138585d7eff1b251d80ea20a22.jpg 2560w,\n/static/f2d285ad9bd918792ad7f1507e74014a/efd47/659afd138585d7eff1b251d80ea20a22.jpg 3882w","sizes":"(max-width: 1000px) 100vw, 1000px"}}},"categories":[{"name":"frontend"},{"name":"other"}]}}]}}}