Skip to content

Event Handling & Updating Block Attributes

Gambaran Umum

Video ini membahas cara menghubungkan UI dengan block attributes — menyimpan nilai question, mengelola array answers (tambah/edit/hapus), dan memahami pola React untuk immutable state updates.


1. Update Question Attribute

Mendefinisikan Attribute

jsx
attributes: {
  question: { type: 'string' },
  answers: { type: 'array', default: [''] },
  correctAnswer: { type: 'number', default: undefined }
},

Hook Up Question Field

jsx
function EditComponent(props) {
  function updateQuestion(value) {
    // TextControl langsung memberikan value (bukan event)
    props.setAttributes({ question: value });
  }

  return (
    <div className="paying-attention-edit-block">
      <TextControl 
        label="Question:" 
        value={props.attributes.question} 
        onChange={updateQuestion}
        style={{ fontSize: "20px" }}
      />
      {/* ... answers section */}
    </div>
  );
}

Penting: WordPress TextControl component mempassing value langsung ke onChange handler, bukan event object. Ini berbeda dari HTML <input> biasa yang mempassing event.target.value.


2. Looping Answers dengan map()

Konsep

Setiap item di array answers menjadi satu baris input field. Gunakan JavaScript Array.map() untuk loop:

jsx
{props.attributes.answers.map(function(answer, index) {
  return (
    <Flex>
      <FlexBlock>
        <TextControl 
          value={answer}
          onChange={(newValue) => {
            // Update satu item spesifik di array
            const newAnswers = props.attributes.answers.concat([]);
            newAnswers[index] = newValue;
            props.setAttributes({ answers: newAnswers });
          }}
        />
      </FlexBlock>
      <FlexItem>
        <Button onClick={() => markAsCorrect(index)}>
          <Icon icon="star-empty" className="mark-as-correct" />
        </Button>
      </FlexItem>
      <FlexItem>
        <Button isLink className="attention-delete" onClick={() => deleteAnswer(index)}>
          Delete
        </Button>
      </FlexItem>
    </Flex>
  );
})}

Mengapa Tidak Langsung Mutate Array?

Di React, jangan pernah langsung mengubah state:

jsx
// ❌ SALAH — mutasi langsung:
props.attributes.answers[index] = newValue;

// ✅ BENAR — buat salinan, ubah salinan:
const newAnswers = props.attributes.answers.concat([]);  // Copy array
newAnswers[index] = newValue;                            // Ubah copy
props.setAttributes({ answers: newAnswers });             // Set via WordPress

.concat([]) — Trik untuk membuat shallow copy array baru. Array baru ini boleh dimutasi karena bukan state asli.


3. Tambah Answer Baru

jsx
<Button isPrimary onClick={() => {
  props.setAttributes({
    answers: props.attributes.answers.concat([''])  // Tambah empty string ke akhir
  });
}}>
  Add another answer
</Button>

.concat(['']) mengembalikan array baru dengan item tambahan — tidak memutasi array asli. Jangan gunakan .push() karena itu mutasi langsung.


4. Hapus Answer

jsx
function deleteAnswer(indexToDelete) {
  const newAnswers = props.attributes.answers.filter(function(x, index) {
    return index != indexToDelete;
  });
  props.setAttributes({ answers: newAnswers });
}

Penjelasan filter():

  • filter() mengembalikan array baru yang hanya berisi item yang lolos kondisi
  • Untuk setiap item: jika index != indexToDeleteinclude (return true)
  • Item yang index-nya sama dengan yang ingin dihapus → exclude (return false)

5. Focus Otomatis pada Field Baru

Tip dari Brad: Saat user klik "Add another answer", field baru bisa otomatis ter-focus:

Langkah 1: Gunakan undefined alih-alih empty string

jsx
<Button isPrimary onClick={() => {
  props.setAttributes({
    answers: props.attributes.answers.concat([undefined])  // ← undefined, bukan ''
  });
}}>
  Add another answer
</Button>

Langkah 2: Tambahkan autoFocus prop

jsx
<TextControl 
  autoFocus={answer === undefined}  // Auto-focus hanya field yang baru ditambahkan
  value={answer} 
  onChange={...}
/>

Field yang baru ditambah memiliki value undefined (satu-satunya yang undefined), sehingga autoFocus hanya aktif untuk field baru tersebut.


Ringkasan Pola React di WordPress Blocks

OperasiPendekatan
Update satu item di arrayCopy array dengan .concat([]), ubah copy, setAttributes()
Tambah item ke array.concat(['']) untuk menambah tanpa mutasi
Hapus item dari array.filter() untuk membuat array baru tanpa item tertentu
Jangan pernahLangsung mutasi props.attributes

Alur Data:

User types in field
  → onChange fires
    → Create copy of answers array
      → Modify the copy
        → props.setAttributes({ answers: newCopy })
          → React re-renders component
            → UI ter-update