Skip to content

Repository untuk belajar React versi 18.2.0. Sumber belajar dari Parsinta.com

Notifications You must be signed in to change notification settings

sejutaimpian/belajar-react-parsinta

Repository files navigation

Catatan/Rangkumanku saat belajar

Daftar Isi
  1. Setup React Dengan Vite
  2. Kita Butuh Prettier
  3. Kita Butuh Desain
  4. React Components
  5. Nested Seperti Ini Salah
  6. useState
  7. Ekstrack ke dalam komponen
  8. useState dengan Object
  9. Manipulasi State

1. Setup React Dengan Vite

  • Tidak lagi menggunakan class, tapi menggunakan function
  • Vite
npm create vite@latest my-react-app -- --template react
cd my-react-app
npm i
npm run dev

Go πŸ”

2. Kita Butuh Prettier

  npm install --save-dev --save-exact prettier
  • Buat file .prettierrc.json di root directory lalu buat configurasi disana
{
"tabWidth": 2,
"singleQuote": true,
"jsxSingleQuote": true,
"semi": false
}
  • File .prettierrc.json berguna untuk meminimalisir conflict pada kerja tim (github) karena perbedaan format
  • Daripada menjalankan command format secara terus-menerus, lebih baik gunakan fitur format on save. Caranya install plugin prettier pada vscode, pergi ke preferece, search format on save, lalu check (enable).

Go πŸ”

3. Kita Butuh Desain

npm install -D tailwindcss postcss autoprefixer
  • Buat file Tailwind config dengan perintah
npx tailwindcss init -p
  • Format jika ingin
  • Konfigurasi path Tailwind
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
  • Buat file Tailwind directive pada src
@tailwind base;
@tailwind components;
@tailwind utilities;
  • import pada main.jsx
  • restart npm run dev
  • Coding pada App.jsx untuk test Tailwind

Go πŸ”

4. React Components

  • React akan lebih untung menggunakan Component

  • Menambakan class pada React menggunakan className

  • Nama component harus berformat TitleCase

  • Permasalahan-permasalahan jika tanpa component yaitu, HTML memang mempunyai component seperti button, tapi itu hanya bawaan dan tidak memiliki style apapun. Jika suatu hari nanti kita memberikan style pada button, lalu membutuhkannya kembali, maka kita harus membuat button baru lalu memberikan style lagi (redudansi)

Go πŸ”

Component fix/absolute data.

function Button() {
  return (
    <button className='bg-blue-600 text-white px-4 py-2 rounded'>
      Sign In
    </button>
  )
}

Cara memanggilnya: <Button /> atau <Button></Button>

Muncul permasalahan: Bagaimana jika textnya ingin dijadikan relative?

Go πŸ”

Component relative data dengan props

  • Menggunakan props
function Button(props) {
  return (
    <button className='bg-blue-600 text-white px-4 py-2 rounded'>
      {props.text}
    </button>
  )
}

Cara memanggilnya: <Button text='Register' />

Muncul permasalahan: Bagaimana jika isi text ingin ditambahkan component lain?

Go πŸ”

Component relative data dengan children

install tabler-icons

npm install @tabler/icons --save
  • Menggunakan props.children
// Component
function Button(props) {
  return (
    <button className='bg-blue-600 text-white px-4 py-2 rounded'>
      {props.children}
    </button>
  )
}

// Pemanggilan
<Button>
    <IconBrandTwitter />
    Login
</Button>

Muncul permasalahan: Bagaimana jika ingin menggunakan kedua cara diatas secara bersamaan, yaitu props.text dan props children?

Go πŸ”

Component relative data dengan pengkondisian props.text dan props.children

  • Menggunakan Logical Operators Or ||
function Button(props) {
  return (
    <button className='bg-blue-600 text-white px-4 py-2 rounded'>
      {props.text || props.children}
    </button>
  )
}

Cara memanggilnya seperti 2 component sebelumnya.

Muncul permasalahan: jika kita ingin memberikan style kepada icon, maka kita akan mengulang (redudansi) styling setiap kali menambahkan icon baru

Go πŸ”

Tailwind arbitrary variant untuk children svg/icon

[&>svg]:w-5 [&>svg]:h-5 [&>svg]:stroke-1

Muncul permasalahan: button defaultnya memiliki property type, onchange, dsb. Bagaimana cara menambahkannya ke component?

Go πŸ”

Menambahkan 1 property type pada component Button

  • Destructuring object props
// Component
function Button(props) {
  const { children, text, type } = props
  return (
    <button
      type={type}
      className='[&>svg]:w-5 [&>svg]:h-5 [&>svg]:stroke-1 flex items-center gap-x-2 bg-blue-600 text-white px-4 py-2 rounded'
    >
      {text || children}
    </button>
  )
}

// Pemanggilan
<Button type='submit'>
    <IconBrandFacebook />
    Register
</Button>
<Button type='button'>
    <IconBrandTwitter />
    Login
</Button>

Destructuring object props:
const {children, text, type} = props;
Sama dengan:
const children = props.children;
const text = props.text;
const type = props.type;

Muncul permasalahan: bagaimana jika kita ingin menambahkan property yang lain? tidak elok jika harus ditambahkan satu-satu.

Go πŸ”

Menambahkan banyak propert dengan spread syntax

// Component
function Button(props) {
  const { children, text } = props
  return (
    <button
      {...props}
      className='[&>svg]:w-5 [&>svg]:h-5 [&>svg]:stroke-1 flex items-center gap-x-2 bg-blue-600 text-white px-4 py-2 rounded'
    >
      {text || children}
    </button>
  )
}

// Pemanggilan
<Button type='submit' onClick={() => console.log('Register')}>
    <IconBrandFacebook />
    Register
</Button>
<Button type='button' onClick={() => console.log('Login')}>
    <IconBrandTwitter />
    Login
</Button>

Muncul permasalahan: bagaimana jika kita ingin menambahkan style yang berbeda pada component?

Go πŸ”

Component dengan props className

function Button(props) {
  const { className, children, text } = props
  return (
    <button
      {...props}
      className={`${className} [&>svg]:w-5 [&>svg]:h-5 [&>svg]:stroke-1 flex items-center gap-x-2 text-white px-4 py-2 rounded`}
    >
      {text || children}
    </button>
  )
}

Gunakan backtick `` untuk menggunakan Template literals (Template strings)
Cara print: ${className}

Muncul permasalahan: bagaimana jika kita ingin memberikan style default?

Go πŸ”

Component dengan props className default

  • Gunakan default variable:
    className = 'bg-blue-600'
function Button(props) {
  const { className = 'bg-blue-600', children, text } = props
  return (
    <button
      {...props}
      className={`${className} [&>svg]:w-5 [&>svg]:h-5 [&>svg]:stroke-1 flex items-center gap-x-2 text-white px-4 py-2 rounded`}
    >
      {text || children}
    </button>
  )
}

Go πŸ”

CLSX

clsx berguna untuk merapikan className kedalam function clsx.

npm i clsx
import clsx from 'clsx'

className={clsx(
    className,
    '[&>svg]:w-5 [&>svg]:h-5 [&>svg]:stroke-1 flex items-center gap-x-2 text-white px-4 py-2 rounded'
)}

Go πŸ”

Memanggil props tidak dengan attribute

<Button
    {...{
        type: 'button',
        onClick: () => console.log('Github Clicked'),
    }}
>
    <IconBrandGithub />
    Register
</Button>
  • Pemanggilan props dengan cara ini lebih baik digunakan ketika value dan property nya sama.
    Contoh:
// Anggap ini value & property nya sama
const type = 'submit'
const onClick = () => console.log('Github Clicked')
// Pemanggilan props
<Button {...{ type, onClick }}>
    <IconBrandGithub />
    Register
</Button>

Go πŸ”

Menambahkan type default overridingable

  1. Tambahkan variable type beserta default value ke dalam destructuring props.
  2. Tambahkan property type={type} pada tag button yang ada di compenent Button
  3. Property type bisa dioverride pada property component Button

Go πŸ”

5. Nested seperti Ini salah

Prettier printWidth, bracketSpacing, dan bracketSameLine

// .prettierrc.json

"printWidth": 80,
"bracketSpacing": true,
"bracketSameLine": true

Go πŸ”

Cara lain export default

  • Jika ada lebih dari satu component pada 1 file, maka export default nya dapat dipindahkan ke akhir code.
export default App

Ketika saya melakukan ini, muncul error "Requested module does not provide export named 'default'" sehingga tampilan website kosong tanpa component. Cara memperbaikinya unik sekali, hanya dengan cara save file main.jsx. Unik bukan? padahal file main.jsx tidak disentuh.

Go πŸ”

Cara lain membuat function component

  • Cara lain untuk membuat function component yaitu dengan menggunakan style ES6. Namanya Stateless Function Component (Arrow function)
const App = () => {
  const type = 'submit'
  const onClick = () => console.log('Github Clicked')
  return (
    <div className='bg-slate-900 grid place-content-center min-h-screen'>
      <div className='flex gap-x-2'>
        <Button {...{ type, onClick }}>
          <IconBrandGithub />
          Register
        </Button>
      </div>
    </div>
  )
}

Go πŸ”

Kelebihan function component ES6

  • Kelebihan function component ES6 adalah ketika return nya hanya satu baris menjadi singkat karena tidak perlu menulis return.
const Title = () => <h1>Hello World</h1>

Go πŸ”

Return JSX tidak menerima lebih dari 1 node

  • Return JSX tidak menerima lebih dari 1 node. Jika ingin memaksakan lebih dari satu node, maka bisa diakali dengan node Fragment from react atau empty tag <></>
// Fragment from react
const Title = () => (
  <Fragment>
    <h1>Hello World</h1>
    <h2>Hello Globe</h2>
  </Fragment>
)

// Empty Node
const Title = () => (
  <>
    <h1>Hello World</h1>
    <h2>Hello Globe</h2>
  </>
)

Go πŸ”

Nested function components

  • Jangan pernah gunakan nested function components walaupun ini valid, karena kata react sendiri ada bug disana (lelet)
export default function App() {
  function Button(props) {
    const { className = 'bg-blue-600', children, text, type = 'submit' } = props
    return (
      <button
        {...props}
        type={type}
        className={clsx(
          className,
          '[&>svg]:w-5 [&>svg]:h-5 [&>svg]:stroke-1 flex items-center gap-x-2 text-white px-4 py-2 rounded'
        )}>
        {text || children}
      </button>
    )
  }
  const type = 'submit'
  const onClick = () => console.log('Github Clicked')
  return (
    <div className='bg-slate-900 grid place-content-center min-h-screen'>
      <div className='flex gap-x-2'>
        <Button {...{ type, onClick }}>
          <IconBrandGithub />
          Register
        </Button>
      </div>
    </div>
  )
}

Go πŸ”

Memisahkan file component

  • Buat folder baru pada src dengan nama Components
  • Buat file baru dengan nama Button.jsx
  • Cut component Button pada file App.jsx ke file Button.jsx
  • Import component Button pada file App.jsx
  import Button from './Components/Button'
  • Export Button pada file Button.jsx
export default Button
  • Import cslx
import clsx from 'clsx'

Go πŸ”

Inline destructuring props

  • Deklarasi destructuring porps pada Button dapat diinlinekan (intina mah dina parameter function Button) dengan tambahan parameter ...props
export default function Button({ className = 'bg-blue-600', children,  text, type = 'submit', ...props }) {
  ....
}

Go πŸ”

Membuat component memiliki banyak component

  • Saat yang tepat untuk membuat component memiliki banyak component adalah seperti kasus Card
  • Kurang nyaman jika harus membuat folder untuk turunan component

Cara component memiliki banyak component

  1. Menggunakan props pribadi
// Component Card
export default function Card({ children, title, footer }) {
  return (
    <div className='shadow'>
      <h1 className='text-2xl font-semibold'>{title}</h1>
      <div className='leading-relaxed'>{children}</div>
      <div className='bg-slate-50'>{footer}</div>
    </div>
  )
}

// Pemanggilan Component
<Card title='Hello World' footer={<Button>Register</Button>}>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit.
</Card>
  1. Component wrap/bind
// Component
function Card({ children, title, footer }) {
  return (
    <div className='shadow'>
      <h1 className='text-2xl font-semibold'>{title}</h1>
      <div className='leading-relaxed'>{children}</div>
      <div className='bg-slate-50'>{footer}</div>
    </div>
  )
}

function Title({ children }) {
  return <h1 className='text-2xl'>{children}</h1>
}
function Footer({ children }) {
  return <div className='bg-slate-50'>{children}</div>
}

Card.Title = Title
Card.Footer = Footer

export default Card

// Pemanggilan
<Card>
  <Card.Title>Hello React</Card.Title>
  Lorem ipsum dolor sit, amet consectetur adipisicing elit.
  <Card.Footer>
    <Button>Register</Button>
  </Card.Footer>
</Card>
  1. Upgrade component wrap/bind
// Component
function Card({ children }) {
  return (
    <div className='shadow rounded-lg overflow-hidden bg-white'>{children}</div>
  )
}
function Title({ children }) {
  return (
    <div className='p-4 border-b'>
      <h1 className='text-xl'>{children}</h1>
    </div>
  )
}
function Body({ children }) {
  return <div className='leading-relaxed p-4'>{children}</div>
}
function Footer({ children }) {
  return <div className='bg-slate-50 p-4'>{children}</div>
}
Card.Title = Title
Card.Body = Body
Card.Footer = Footer
export default Card

// Pemanggilan
<Card>
  <Card.Title>Hello React</Card.Title>
  <Card.Body>
    Lorem Lorem, ipsum dolor sit amet consectetur adipisicing elit.
    Fugiat, dicta. Lorem ipsum dolor sit, amet consectetur adipisicing
    elit. Aut, aperiam?
  </Card.Body>
  <Card.Footer>
    <Button>Register</Button>
  </Card.Footer>
</Card>

Go πŸ”

6. useState

  • useState hadir untuk HMR, yaitu perubahan langsung/live pada browser. Penggunaan let apalagi const tidak memengaruhi HMR.
export default function App() {
  const [name, setName] = useState('Default')
  function handleClick() {
    setName('Eris')
  }
  return (
    <PlaceContentCenter>
      <div>{name}</div>
      <Button onClick={handleClick}>Change Name</Button>
    </PlaceContentCenter>
  )
}
  • Variable pada useState tertinggal satu langkah setelah melakukan setState. Cara mengakalinya adalaha dengan cara membuat variable baru berawalan next, seperti nextName
function handleClick() {
  const nextName = 'Eris'
  setName(nextName)
}
  • Ketika ingin menggunakan function, jangan tambahkan () agar function tersebut tidak langsung/otomatis dipanggil di awal
  • Pemanggilan setState tidak bisa dilakukan berulang dalam satu waktu, karna yang terjadi hanya akan menjalankan handle secara sekali. Untuk mengakali hal tersebut, dapat menggunakan updater. variable prevState dapat diganti dengan apapun.
export default function App() {
  const [count, setCount] = useState(0)
  function handleClick() {
    // setCount(count + 1)
    setCount((prevCount) => prevCount + 1)
  }
  return (
    <PlaceContentCenter>
      <div>{count}</div>
      <Button onClick={handleClick}>+1</Button>
      <Button
        onClick={() => {
          handleClick()
          handleClick()
          handleClick()
        }}>
        +3
      </Button>
    </PlaceContentCenter>
  )
}
  • Ketika memanggil function didalam arrow function, pastikan untuk menambahkan ()

Go πŸ”

7. Ekstrack ke dalam komponen

  • Codingan Counter pada video sebelumnya dapat dijadikan komponen terpisah. Caranya buat file baru pada folder Components sebagaimana biasanya.
  • Kadangkala komponen membutuhkan variable state yang terdapat pada komponen lainnya atau ingin mengirim data. Untuk mengakali hal tersebut, state dapat ditransfer melalui props. Catatan, jika state nya hanya untuk 1 komponen, sebaiknya simpan di komponen yang bersangkutan.
  • Jika props & state memiliki nama yang sama, maka bis dibongkar menjadi <Counter {...{ count, setCount }} />
  • Kalian juga dapat menambahkan initial props

Go πŸ”

8. useState dengan Object

  • Setup
  • Install tailwindcss-forms
// Install
npm install -D @tailwindcss/forms

// tailwind.config.js
module.exports = {
  theme: {
    // ...
  },
  plugins: [
    require('@tailwindcss/forms'),
    // ...
  ],
}
  • label dan input dapat dijadikan komponen tersendiri agar stylenya seragam
  • comment pada jsx menggunakan /* comment */
  • Membuat state untuk name dan email seperti biasa (array) akan menjadi melelahkan jika isi formnya bertambah banyak. Solusinya adalah dengan useState Object.
// useState object
const [form, setForm] = useState({
  name: '',
  email: '',
})

// setter object useState
function onChange(event) {
  setForm({ ...form, [event.target.name]: event.target.value })
}

// menampilkan
<p>Name: {form.name || '----'}</p>
<p>Email: {form.email || '----'}</p>
  • Menambahkan form onSubmit
// form
<form onSubmit={onSubmit}>...</form>
// function onSubmit
function onSubmit(event) {
  event.preventDefault()
  console.log(form)
}

Go πŸ”

9. Manipulasi State

  • Membuat Component Todo

Pastikan bahwa path import komponennya sudah benar.
Path import komponen pada App.jsx tidak sama dengan import komponen pada komponen karena beda struktur folder. Sehingga jangan dicopas.

  • Manipulasi state ada 2 (berdasarkan yang diajarkan dalam video), yaitu map() untuk menambah state variable array dan filter() untuk menghapus state variable array.

Go πŸ”

About

Repository untuk belajar React versi 18.2.0. Sumber belajar dari Parsinta.com

Resources

Stars

Watchers

Forks

Packages

No packages published