Group Details Private

Problem Solver

The participant of BaliJS monthly quiz. Join by invitation only.

  • @Kadek-Darmayasa dan @recovdot halo selamat datang di forum BaliJS. Jgn lupa join Telegram grup kita jg yah

    posted in Diskusi Umum
  • Kenapa NestJs?

    Kali ini gue bakal share pengalaman mencoba nestjs, alasan pakai nestjs karena agak mirip sama symfony karena sempat dulu belajar kalau di symfony itu pakai xml buat depedency injection nya. Ya agak mirip lah 😊 walau beda bahasa typescript dengan php.

    Nah dalam perjalanan mengarumi framework ini bayak hal yang gue alami dan kadang bikin buka banyak tab buat lihat stack overflow sama github buat ngerti source code. Pertama kali gue install itu pakai NX (monorepo) gitu biar keren 😎 , canda biar simple aja males project kesebar gitu biar git nanti satu aja.

    Nah selain menggunakan NX di dokumentasi bisa bikin pakai command line interface bisa lihat pada bagian NestJS - First Setup , yang pakai react, angular atau build tool lainnya pasti ngerti mirip - mirip gitu. Selain itu juga banyak juga boilerplate (kayak startup project simplenya) tapi walau bagus bisa hemat waktu enggak ulang - ulang dan mulai dari dasar. Tapi penggunaan boilerplate ini ada kelemahan kadang - kadang pas run banyak yang error, jadi sama aja sih pakai ama enggak. Salah satu boilerplate yang gue rekomendasikan adalah Awesome Nest Boilerplate disana dia untuk database pakai typeorm untuk ORM (Object relation Mapping) ya kayak sebuah assembler otomatis gitu pakai class decorator. untuk API akses menggunakan swagger (kalau simplenya sih swagger CRUD API biasa tapi ada playgroundnya mirip postman), jadi tinggal buka api bisa langsung test di tempat, hampir mirip si GraphQL. Oh ya selain itu ada juga file yang dulu aku enggak ngerti buat apa di sana di pakai main.hmr.ts itu sebenarnya apa kan ada hmr mungkin maksudnya hot module replacement tapi kan aku pakai buat bikin backend API rasanya kagak perlu di pakai

    Untuk bagian tutorial ada di bawah sesi curhatnya, kalau mau langsung pingin tahu sesuai judul bisa baca setelah curhat ℹ

    Curhat (Boleh Baca Boleh Enggak)

    Jujur aja aku kan kemarin ikut kompetisi RICH kayak kompetisi startup gitu, nah startup layarjasa platform pengalur jasa mirip beres*id kalau mau follow bisa lihat di IG Layarjasa. Nah kan di umumin itu kalau enggak salah H-3 gitu kalau enggak salah, pertama aku pesimis karena bikin sendiri, walau nama teammnya itu sih 4 orang 😥 tapi tetep aku kebut biar jadi yang kan deadline langsung tak kebutin, selesai juga dalam 1 hari Heehehe. Untungnya di sana ada asaramnya Thank to InbisTohpati walau makanan catering agak pedas menurut aku yang enggak suka pedas, kasihan sambal enggak aku makan.

    Disanan kan kami (aku) yang karena selama 3 hari cuma aku aja yang hadir dan ditemanini sama saudara terus hari 2 dan 3 sendiri, untuk presentasi dibantu sama mas ay buat presentasi itu pun ngebut juga bikin jam 8 selesai jam 12 malam sampai di usir sama satpam 🚓 wkwkwk kacau. Karena aku orang introvert jarang bicara sama manusia dan lagi proses recovery mental di psyciater terus enggak ada persiapan mau pitching apa jadi hancur dah 💥

    Walau enggak berhasil jadi tenant yang setidaknya dapet relasi lah terus dapat belajar enteprenur terus teknik berkomunikasi, terus ternyata bisa pakai alat CNC machine buat bikin proyek IoT.

    Module pada nestjs

    Nestjs ini berdasar dari Angular js maka terms atau istilah dipakai agak mirip nah nest ini aplikasi kita itu berdiri dari modules - module nah nantinya module harus kita importkan ke AppModule kalau enggak nanti enggak di baca 💩 sempat dulu bikin module kok enggak ada di api ternyata belum ke import, selain itu juga ada kesalahan yang sering di alami pemula, kalau enggak pakai cmd buat generate module atau service biasanya lupa buat nambah di field provides nama service yang buat di Injectkan jadinya malah enggak bisa di baca sama modulnya.

    Mengenal Nestjs-query

    Pertama kali mengenal nestjs query karena gue merasa malas melakukan repetisi buat cuma bikin crud aja padahal kan itu repetisi kalau di symfony dulu tinggal extends Repository class terus inject dah si ORM modelnya, akhirnya coba cari" ketemu ini bisa CRUD cepat terus sekalian ama GraphQL terus bisa integrasi sama banyak jenis database kalau gue kan pakai mongodb terus pakai typegoose jadi simple bikin crud enggak lama terus enggak perlu bikin resolver buat DTOnya 🌈

    Sebenarya untuk contohnya bisa dilihat di repository ada folder example jadi coba gue bikin yang lebih simple aja kali ya atau gue jelasin aja bagian yang ribetnya aja bagian folder 📂 berikut

    import { NestjsQueryGraphQLModule } from '@nestjs-query/query-graphql';
    import { Module } from '@nestjs/common';
    import { NestjsQueryTypegooseModule } from '@nestjs-query/query-typegoose';
    import { TagInputDTO } from './dto/tag-input.dto';
    import { TagDTO } from './dto/tag.dto';
    import { TagEntity } from './tag.entity';
    
    @Module({
      imports: [
        NestjsQueryGraphQLModule.forFeature({
          imports: [NestjsQueryTypegooseModule.forFeature([TagEntity])],
          resolvers: [
            {
              DTOClass: TagDTO,
              EntityClass: TagEntity,
              CreateDTOClass: TagInputDTO,
              UpdateDTOClass: TagInputDTO,
              enableAggregate: true,
            },
          ],
        }),
      ],
    })
    export class TagModule {}
    
    

    nah kalau dilihat sekilas intinya di bagian import itu entitinya (ORM). Nah Kan ada DTOClass nah ini akan di mapping menjadi GraphQL ObjectType terus Create dan Update itu itu nantinya jadi Input Type bisa buat untuk di mutation pada bagian GraphQL jadi nantinya kalau di resolver itu jadi arguments tapi ini langsung terhubung sama database. enable agregate itu buat namah fitur seperti groupBy, count, sum, avg, min, dan max (sortir dan fiter simplenya). Kayaknya dah jelas untuk bagian ini

    Nah untuk di app`modulenyanya tinggal taruh seperti ini

    import { Module } from '@nestjs/common';
    import { GraphQLModule } from '@nestjs/graphql';
    import { TypegooseModule } from 'nestjs-typegoose';
    import { GqlContext } from './auth.guard';
    import { TagModule } from './tag/tag.module';
    import { TodoItemModule } from './todo-item/todo-item.module';
    import { SubTaskModule } from './sub-task/sub-task.module';
    import { mongooseConfig } from '../../helpers';
    
    const { uri, ...options } = mongooseConfig('typegoose', {
      useNewUrlParser: true,
      useUnifiedTopology: true,
      useCreateIndex: true,
      useFindAndModify: false,
    });
    
    @Module({
      imports: [
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        TypegooseModule.forRoot(uri!, options),
        GraphQLModule.forRoot({
          autoSchemaFile: 'schema.gql',
          context: ({ req }: { req: { headers: Record<string, string> } }): GqlContext => ({ request: req }),
        }),
        SubTaskModule,
        TodoItemModule,
        TagModule,
      ],
    })
    export class AppModule {}
    

    Ada 5 module di pakai 2 untuk setup database dan graphql kemudian 3 buatan sendiri yaitu SubTaskModule, TodoItemModule dan TagModule. Pada module graphql itu kan ada property autoSchemaFile nah ini nanti merupakan lokasi dimana gql filenya di buat yang letaknya root project directory jadi nanti setelah yarn start (jalan server) nanti pas proses build akan membuat file dengan nama schema.gql yang di dalamnya ada kayak sejenis graphql type baik untuk mutation, query, inputtype, object type, schalar dan lainnya. Jangan coba hapus atau modif file ini kalau enggak bisa 💥

    Setup Database Gimana 😕

    Bisa pakai docker, install mongodb manual atau bisa juga pakai yang lainnya ada sempat baca bisa pakai npm module yang seolah" mereplika mongose cara kerja jadi bisa enggak perlu install mongodb cukup dengan yarn atau npm aja.

    Oh ya nestjs-query aku baru coba untuk tipe database NoSQL aku belum coba untuk yang bertipe SQL jadi belum bisa kasi banyak bocoran, mungkin kalau nanti ada project pakai SQL aku coba pakai.

    Mengakses GraphQL Playground

    Tahap ini paling asik sih buat main - main coba graphql kita yang telah di buat, enaknyak pakai nestjs-query itu udah support pagination jadi enggak perlu pusing dari 0 hehehh, bagi yang pernah pakai gatsby graphql paging query hampir sama, apakah ini sebuah konspirasi besar (😆 ).untuk akses bisa buka pada path/graphql` untuk dokumentasi dan schema ada di tab sebelah kanan tinggal di klik, kalau bingung pas mau ketik query tenang ada autocomplete sama lint nya heheee top dah

    Catatan

    Sebenarnya mau bikin tutorial bikin tutorial auth pakai nestjs + jwt auth + graphql takutnya materinya terlalu kebesaran buat di baca, mungkin yang ada saran bisa tinggalkan di komentar untuk di bahasa atau bisa kontak wa saya 087705635438, bisa juga kita belajar bersama 1 to 1 biar belajar enggak sendiri walau bukan cewek guenya hahahah. Kalau belajar 1 to 1 paling bisa sekitaran jam 8 maleman, maklum tinggal di desa ngurus hewan peliharan sama tanaman siang ngoding, malemnya ngewibu, kayaknya udah OOT dah 3 jam berasa cepat banget ya. See you on next post on next week :mailbox_closed:

    posted in Back End
  • @krismaputra halo bli, selamat datang. Ditunggu kontribusi nya di komunitas BaliJS 🙏 🙏

    posted in Diskusi Umum
  • @Andika-Wira halo andika, welcome! 😊

    posted in Diskusi Umum
  • Seputar Frontend

    • Mempelajari React Hooks lebih dalam, sebuah module pembelajaran React Hooks ditulis dengan Bahasa Indonesia -- React Hooks Deep Dive

    Seputar Backend

    • Packing Nodejs dalam sebagai Single Binary -- Boxed Node

    Seputar Tutorial

    posted in Newsletter
  • @mahend_ halo2 Mahend 🙏 selamat datang, silakan kalo mau bertanya2 atau sharing di forum BaliJS 🙏 🙏

    posted in Diskusi Umum
  • Use Context

    Berbicara tentang context, simpelnya context ini adalah global state manajemen bawaan React. Dengan menggunakan context, kita bisa mempasing data/mengirim data dari parent komponen ke child komponen tanpa harus menggunakan props untuk melewati level2nya.

    Di dokumentasi React sendiri sempat disinggung mengenai component tree, ini menjadi maksud bahwa cara berfikir React, adalah struktur hierarki, yang artinya komponen terbagi2 menjadi susunan kecil piece by piece, sub by sub atau level by level. Perumpamaannya seperti ini, ada komponen orang tua dan ada komponen anak-anak:

    • FilterableProductTable
      • SearchBar
      • ProductTable
        • ProductCategoryRow
        • ProductRow

    React menggunakan konsep props dan state untuk berinteraksi antara komponen dengan proses inputan dan data. Konsep yang cerdas menurut saya, tapi masalahnya adalah ada beberapa pertanyaan 'apakah state ini berlaku di semua komponen? Atau hanya di komponen itu sendiri saja?, Ketika komponen saya nantinya sudah banyak cabang2, banyak melalui level sampai 5 level, apa saya harus menggunakan props untuk sharing input terus menerus?'

    Jika kita membaca dokumentasi, React memberikan beberapa solusi tepat dari masalah diatas. 'If you only want to avoid passing some props through many levels, component composition is often a simpler solution than context.' artinya kalau cuman untuk menghindari melewatkan beberapa props melalui banyak level, kita bisa menggunakan komposisi komponen ini cara yang lebih mudah daripada menggunakan context.

    Namun, bila tujuannya untuk sharing data antar komponen yang sifatnya global seperti: authentikasi user, tema, cache data, dan language, maka ini adalah cara yang tepat untuk menggunakan context. Inipun kita juga harus hati-hati dan tepat dalam menggunakannya 'apply it sparingly because it makes component reuse more difficult.'.

    Component Composition

    Ini sebenernya merupakan sebuah komponen pattern yang digunakan untuk membangun komponen dari komponen lain menjadi kesatuan yang lebih besar, istilahnya seperti gotong royong. Tetapi, konsep ini punya aturan, casenya seperti ini anggap saja dalam gotong royong terdapat 2 role, role sebagai ketua kelompok dan role sebagai anggota.

    Aturannya adalah ketika para anggota saling bahu membahu untuk membawa box(misal) maka anggota lain tidak perlu tahu isi box tersebut apa. Tugasnya anggota hanya membawa box tersebut sampai ke tujuan. Sedangkan ketua kelompok tugasnya mengawasi dan menyiapkan box supaya siap dikirim ke pelanggan, seperti *label, rincian, dll`.

    Jika di realitakan dalam bentuk kode, contohnya seperti dibawah ini:

    function Anggota(props){
      return <span>{ props.text }</span>
    }
     
    function Anggota_Dua(props){
      return <button>{ props.render }</button> // Cuman sebagai terusan untuk merender <Anggota/>
    }
     
    function KetuaKelompok(){
      const btnText = <Anggota text="Click Me" />;
      return <Anggota_Dua render={btnText}/>
    }
    
    <KetuaKelompok/>
    

    Pada intinya komposisi komponen ini tujuannya adalah sebagai terusan yang dipassing/dikirim melalui props. Mirip seperti konsep { props.children }, lebih jelasnya bisa lihat example. Cara ini lebih tepat dan mudah dibandingkan dengan context

    Context

    Seperti yang dijelaskan diatas, context adalah global state management. Sebenernya harusnya disini saya langsung saja menjelaskan bagaimana cara dan konsep useContext() hooks, cuman karena ada beberapa proses yang berhubungan jadi saya akan jelaskan secara detail.

    Pada beberapa source biasanya menggunakan useReducer() untuk melakukan manipulasi state, padahal case yang dialami hanya seperti dibawah ini:

    // Reducer
    export const Reducer = (state = initialState) => {
        ...
        case StepActionStatus.ADD_FORM_DATA_PREV: {
            return {
                ...state,
                storedFormData: [...state.storedFormData.concat(action.payload.allFields)].reverse().sort()
            }
        }
        ...
    }
    

    Pointnya tujuan dari kode itu adalah hanya untuk menggabungkan data di store dengan payload (context), tentunya cara ini malah menyulitkan, kalau ada cara yang lebih mudah kenapa cari yang sulit:). Maka dari itu, selagi casenya ga kompleks2 banget, pake useState() aja udah cukup (bahkan ini cara yang lebih tepat).

    Ini adalah cara best praktis yang umumnya sering kali digunakan, yaitu dengan menggunakan suatu fungsi untuk melakukan perubahan nilai pada context. Disini saya buat 2 versi, yaitu dengan menggunakan pure useState, dan dengan bantuan useCallback, Perhatikan kode dibawah ini:

    const initialState = {
        state: ''
    }
    
    export const Context = React.createContext<typeof initialState | any>(undefined);
    
    function ContextProvider(props: React.PropsWithChildren<{}>) {
        const [state, setState] = React.useState(initialState);
    
        return (
            <Context.Provider value={{ state, setState }}>
                {props.children}
            </Context.Provider>
        )
    }
    
    export default ContextProvider;
    
    
    const contextState = React.useContext(Context);
    const { setState } = contextState;
    

    Pada kode diatas, value pada Context.Provider diambil dari local state, jadi ketika context ini di use maka value yg didapat adalah state & setState. Seperti yang dijelaskan pada module sebelumnya, [state, setState] variabel pertama untuk nilai, variabel kedua untuk merubah nilai.

    Untuk cara yang kedua, hampir mirip dengan cara yang pertama, cuman bedanya ditambah useCallback, perhatikan kode dibawah ini:

    const initialStateCallback = {
        callbackState: ''
    }
    
    export const ContextCallback = React.createContext<typeof initialStateCallback | any>(undefined);
    
    function ContextCallbackProvider(props: React.PropsWithChildren<{}>) {
        const [callbackState, setCallbackState] = React.useState(initialStateCallback);
    
        // With useCallback (prefered)
        const setContextCallback = React.useCallback(
            newState => {
                return setCallbackState({
                    callbackState: { ...newState }
                })
            },
            [callbackState, setCallbackState]
        );
    
        const getContextCallback = React.useCallback(
            () => ({ setContextCallback, ...callbackState }),
            [callbackState, setContextCallback]
        );
    
        return (
            <ContextCallback.Provider value={getContextCallback()}>
                {props.children}
            </ContextCallback.Provider>
        )
    }
    
    export default ContextCallbackProvider;
    
    
    const contextCallbackState = React.useContext<any>(ContextCallback);
    const { setContextCallback } = contextCallbackState;
    

    Kamu juga bisa menginitialize useCallback() nya di komponennya langsung cuman saya lebih prefer di providernya sih. Contoh kodenya seperti ini:

    const handlerCallback = React.useCallback(() => {
        setState({
            state: 'Transform to useCallback()',
        })
    }, [contextState.state, setState]);
    
    <button onClick={handlerCallback}>Click Me</button>
    

    Alasannya mengapa menggunakan useCallback() adalah karena ini 'Using an arrow function in render creates a new function each time the component renders, which may break optimizations based on strict identity comparison.' artinya arrow function () => { ... } ini akan membuat fungsi baru setiap kali komponen dirender ulang, ini bisa menyebabkan memory leaks.

    Next Hooks

    Lihat versi full module penggunaan hooks secara lengkap dalam Bahasa Indonesia
    https://github.com/natserract/react-hooks-deepdive. Kamu juga bisa ikut berkontribusi, pull request are welcome 😉

    posted in Front End
  • @wayanjimmy yoi kak, aku pake plugin ini kalo di vscode biar bisa generate jsdoc otomatis 😀 https://marketplace.visualstudio.com/items?itemName=stevencl.addDocComments

    posted in Front End
  • @natserract wah baru tau ternyata jsdoc disupport vscode, bisa meningkatkan developer experiencenya nih

    posted in Front End
  • Bagi para developer, kata utility tentunya sudah tak asing di dengar, hampir di setiap project, utility ini akan selalu dibuat. Utility biasanya isinya adalah functions2, atau service, yang sifatnya reusable atau istilahnya 'write once, use many times'.

    Di tulisan kali ini kita tidak akan membuat utility, tpi lebih ke bagaimana mengembangkan utility yang kamu buat supaya lebih readable, dan bisa mudah digunakan oleh developer lain nantinya.

    Tapi sebelum itu, ada beberapa pertanyaan, apa bener javascript itu dynamic typing?, coba perhatikan kode dibawah ini:

    index.js
    Screen Shot 2020-12-22 at 23.25.51.png
    Dalam kode diatas, type tidak didefinisikan, tapi Javascript sudah secara otomatis mendeteksi type ketika value dibuat. Perhatikan lagi, ketika cursor di hover
    Screen Shot 2020-12-22 at 23.26.00.png
    Dari sini kita tahu, bahwa Javascript itu Dynamic Typing

    Sebelum ke maincase, bisa baca source ini dlu:

    Main case

    Ketika membuat sebuah function, pastinya ada nama function, parameter(optional), dan return dari function tersebut, example:

    index.js
    Screen Shot 2020-12-23 at 09.36.59.png
    Mungkin kalian sudah tau, maksud dari cara kerja function ini, ekspetasinya adalah return dari function ini harus mengembalikan nilai true, yang isi parameter typenya mempunyai masing-masing tipe data nya adalah string.

    Tapi problemnya, ketika function ini digunakan, apakah argumen yang dimasukkan di function isShouldBeString() selalu bertipe data string? bisa jadi tidak!.
    Mengapa? karena type dari kedua parameter tersebut tidak di define/definisikan.

    Jika menggunakan TypeScript, tentu masalah ini akan selesai sepersekian detik. Tpi bagaimana pengguna JavaScript menyelesaikan ini? "Ya definisiin typenya masbro!"

    Jawabannya 70% hampir betul, definiisin typenya. Tapi tidak dengan type definitions, melainkan JSDoc. Bisa dibantu juga dengan JSDoc eslint plugin, tapi kali ini kita tidak menggunakan eslint.

    What? Apa itu jsdoc?, singkatnya JSDoc itu adalah dokumentasi dari source code yang kita buat, bentuknya simple hanya berupa komen tpi penggunaannya sangat berguna nantinya. Contohnya ada pada kode dibawah ini:
    Screen Shot 2020-12-23 at 17.19.11.png

    Perhatikan pada line 23 - 27, ada 3 tag, pada tag@param, fungsinya untuk membuat dokumentasi dari tipe data dari parameter function isShouldBeString(), kemudian tag @returns artinya apa returnnya, sedangkan tag @example adalah contoh penggunaan dari function tersebut. Selain 3 tag itu, kalian juga bisa menggunakan tag2 lain

    Jika kita hover functionnya, maka hasilnya akan seperti ini
    Screen Shot 2020-12-23 at 17.19.21.png

    Sangat mudah bukan?, disini sangat jelas terlihat bahwa function isShouldBeString() itu maksudnya untuk apa sih, cara penggunaan function ini yang tepat bagaimana, dll. Tentunya ini bisa membantu developer lain untuk bisa mudah mengerti utility yang kita buat.

    So programming it's all about solving problem right? Maka dari itu, bisa mulai dari sekarang untuk disiplin dalam meng-kode. Thanks!

    posted in Front End