Skip to content

docs: translate cloneElement page #567

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 9, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 51 additions & 52 deletions src/content/reference/react/cloneElement.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ title: cloneElement

<Pitfall>

Using `cloneElement` is uncommon and can lead to fragile code. [See common alternatives.](#alternatives)
Menggunakan `cloneElement` adalah hal yang jarang terjadi dan dapat menyebabkan kode yang rentan. [Lihat alternatif yang umum.](#alternatives)

</Pitfall>

<Intro>

`cloneElement` lets you create a new React element using another element as a starting point.
`cloneElement` memungkinkan Anda untuk membuat elemen React baru dengan menggunakan elemen lain sebagai titik awal.

```js
const clonedElement = cloneElement(element, props, ...children)
Expand All @@ -22,11 +22,11 @@ const clonedElement = cloneElement(element, props, ...children)

---

## Reference {/*reference*/}
## Referensi {/*reference*/}

### `cloneElement(element, props, ...children)` {/*cloneelement*/}

Call `cloneElement` to create a React element based on the `element`, but with different `props` and `children`:
Panggil `cloneElement` untuk membuat elemen React berdasarkan `element`, tetapi dengan `props` dan `children` yang berbeda:

```js
import { cloneElement } from 'react';
Expand All @@ -43,42 +43,42 @@ const clonedElement = cloneElement(
console.log(clonedElement); // <Row title="Cabbage">Goodbye</Row>
```

[See more examples below.](#usage)
[Lihat lebih banyak contoh di bawah ini.](#usage)

#### Parameters {/*parameters*/}
#### Parameter {/*parameters*/}

* `element`: The `element` argument must be a valid React element. For example, it could be a JSX node like `<Something />`, the result of calling [`createElement`](/reference/react/createElement), or the result of another `cloneElement` call.
* `element`: Argumen `element` harus merupakan elemen React yang valid. Misalnya, dapat berupa simpul JSX seperti `<Something />`, hasil dari pemanggilan [`createElement`](/reference/react/createElement), atau hasil dari pemanggilan `cloneElement` lainnya.

* `props`: The `props` argument must either be an object or `null`. If you pass `null`, the cloned element will retain all of the original `element.props`. Otherwise, for every prop in the `props` object, the returned element will "prefer" the value from `props` over the value from `element.props`. The rest of the props will be filled from the original `element.props`. If you pass `props.key` or `props.ref`, they will replace the original ones.
* `props`: Argumen `props` harus berupa objek atau `null`. Jika Anda mengoper `null`, elemen yang di-kloning akan mempertahankan semua `element.props` yang orisinal. Sebaliknya, untuk setiap *prop* di objek `props`, elemen yang dikembalikan akan "memilih" nilai dari `props` daripada nilai dari `element.props`. Sisa *props* lainnya akan diisi dari `element.props` yang orisinal. Jika Anda mengoper `props.key` atau `props.ref`, mereka akan menggantikan yang orisinal.

* **optional** `...children`: Zero or more child nodes. They can be any React nodes, including React elements, strings, numbers, [portals](/reference/react-dom/createPortal), empty nodes (`null`, `undefined`, `true`, and `false`), and arrays of React nodes. If you don't pass any `...children` arguments, the original `element.props.children` will be preserved.
* **opsional** `...children`: Nol atau lebih simpul anak. Bisa dari simpul React apa pun, termasuk elemen React, *string*, dan *number*. [*portal*](/reference/react-dom/createPortal), simpul kosong (`null`, `undefined`, `true`, dan `false`), dan senarai dari simpul-simpul React. Jika Anda tidak mengoper argumen `...children` apa pun, `element.props.children` yang orisinal akan tetap dipertahankan.

#### Returns {/*returns*/}
#### Kembalian {/*returns*/}

`cloneElement` returns a React element object with a few properties:
`cloneElement` mengembalikan objek elemen React dengan beberapa properti:

* `type`: Same as `element.type`.
* `props`: The result of shallowly merging `element.props` with the overriding `props` you have passed.
* `ref`: The original `element.ref`, unless it was overridden by `props.ref`.
* `key`: The original `element.key`, unless it was overridden by `props.key`.
* `type`: Sama seperti `element.type`.
* `props`: Hasil dari penggabungan dangkal antara `element.props` dengan `props` yang Anda oper untuk menimpanya.
* `ref`: `element.ref` yang orisinal, kecuali telah ditimpa oleh `props.ref`.
* `key`: `element.key`, yang orisinal, kecuali telah ditimpa oleh `props.key`.

Usually, you'll return the element from your component or make it a child of another element. Although you may read the element's properties, it's best to treat every element as opaque after it's created, and only render it.
Biasanya, Anda akan mengembalikan elemen dari sebuah komponen atau membuatnya sebagai anak dari elemen lain. Meskipun Anda mungkin membaca properti elemen tersebut, sebaiknya Anda memperlakukan setiap elemen sebagai objek tersembunyi setelah dibuat, dan hanya me-*render*-nya.

#### Caveats {/*caveats*/}
#### Catatan penting {/*caveats*/}

* Cloning an element **does not modify the original element.**
* Mengkloning sebuah elemen **tidak mengubah elemen yang orisinal**.

* You should only **pass children as multiple arguments to `cloneElement` if they are all statically known,** like `cloneElement(element, null, child1, child2, child3)`. If your children are dynamic, pass the entire array as the third argument: `cloneElement(element, null, listItems)`. This ensures that React will [warn you about missing `key`s](/learn/rendering-lists#keeping-list-items-in-order-with-key) for any dynamic lists. For static lists this is not necessary because they never reorder.
* Sebaiknya Anda hanya **mengoper *children* sebagai beberapa argumen ke `cloneElement` jika semuanya diketahui secara statis,** seperti `cloneElement(element, null, child1, child2, child3)`. Jika *children* Anda dinamis, oper seluruh senarai sebagai argumen ketiga: `cloneElement(element, null, listItems)`. Ini memastikan bahwa React akan [memperingatkan Anda tentang `key` yang hilang](/learn/rendering-lists#keeping-list-items-in-order-with-key) untuk setiap *list* dinamis. Untuk *list* statis hal tersebut tidak diperlukan karena tidak pernah diurutkan ulang.

* `cloneElement` makes it harder to trace the data flow, so **try the [alternatives](#alternatives) instead.**
* `cloneElement` membuat pelacakan aliran data lebih sulit, jadi **cobalah beberapa [alternatif](#alternatives) sebagai gantinya.**

---

## Usage {/*usage*/}
## Penggunaan {/*usage*/}

### Overriding props of an element {/*overriding-props-of-an-element*/}
### Menimpa props dari suatu elemen {/*overriding-props-of-an-element*/}

To override the props of some <CodeStep step={1}>React element</CodeStep>, pass it to `cloneElement` with the <CodeStep step={2}>props you want to override</CodeStep>:
Untuk menimpa *prop* dari beberapa <CodeStep step={1}>elemen React</CodeStep>, oper ke `cloneElement` dengan <CodeStep step={2}>*props* yang ingin Anda timpa</CodeStep>:

```js [[1, 5, "<Row title=\\"Cabbage\\" />"], [2, 6, "{ isHighlighted: true }"], [3, 4, "clonedElement"]]
import { cloneElement } from 'react';
Expand All @@ -90,11 +90,11 @@ const clonedElement = cloneElement(
);
```

Here, the resulting <CodeStep step={3}>cloned element</CodeStep> will be `<Row title="Cabbage" isHighlighted={true} />`.
Hasil dari <CodeStep step={3}>elemen yang dikloning</CodeStep> akan menjadi `<Row title="Cabbage" isHighlighted={true} />`.

**Let's walk through an example to see when it's useful.**
**Mari telusuri contoh untuk melihat kapan hal tersebut berguna.**

Imagine a `List` component that renders its [`children`](/learn/passing-props-to-a-component#passing-jsx-as-children) as a list of selectable rows with a "Next" button that changes which row is selected. The `List` component needs to render the selected `Row` differently, so it clones every `<Row>` child that it has received, and adds an extra `isHighlighted: true` or `isHighlighted: false` prop:
Bayangkan komponen `List` yang me-*render* [`children`](/learn/passing-props-to-a-component#passing-jsx-as-children)nya sebagai daftar baris yang dapat dipilih dengan tombol "Next" yang dapat merubah baris mana yang dipilih. Komponen `List` perlu me-*render* `Row` yang dipilih secara terpisah, lalu mengkloning setiap anak `<Row>` yang telah diterima, dan menambahkan *prop* `isHighlighted: true` atau `isHighlighted: false`:

```js {6-8}
export default function List({ children }) {
Expand All @@ -108,7 +108,7 @@ export default function List({ children }) {
)}
```

Let's say the original JSX received by `List` looks like this:
Katakanlah JSX asli yang diterima oleh `List` terlihat seperti ini:

```js {2-4}
<List>
Expand All @@ -118,7 +118,7 @@ Let's say the original JSX received by `List` looks like this:
</List>
```

By cloning its children, the `List` can pass extra information to every `Row` inside. The result looks like this:
Dengan mengkloning anaknya, `List` dapat meneruskan informasi tambahan ke setiap `Row` di dalamnya. Hasilnya terlihat seperti ini:

```js {4,8,12}
<List>
Expand All @@ -137,7 +137,7 @@ By cloning its children, the `List` can pass extra information to every `Row` in
</List>
```

Notice how pressing "Next" updates the state of the `List`, and highlights a different row:
Perhatikan saat menekan "Next" akan memperbarui *state* dari `List`, dan menyorot baris yang berbeda:

<Sandpack>

Expand Down Expand Up @@ -232,21 +232,21 @@ button {

</Sandpack>

To summarize, the `List` cloned the `<Row />` elements it received and added an extra prop to them.
Ringkasnya, `List` mengkloning elemen `<Row />` yang diterimanya dan menambahkan *prop* tambahan ke dalamnya.

<Pitfall>

Cloning children makes it hard to tell how the data flows through your app. Try one of the [alternatives.](#alternatives)
Mengkloning *children* mempersulit untuk mengetahui bagaimana aliran data di aplikasi Anda. Coba salah satu [alternatif.](#alternatives)

</Pitfall>

---

## Alternatives {/*alternatives*/}
## Alternatif {/*alternatives*/}

### Passing data with a render prop {/*passing-data-with-a-render-prop*/}
### Mengoper data dengan render prop {/*passing-data-with-a-render-prop*/}

Instead of using `cloneElement`, consider accepting a *render prop* like `renderItem`. Here, `List` receives `renderItem` as a prop. `List` calls `renderItem` for every item and passes `isHighlighted` as an argument:
Daripada menggunakan `cloneElement`, pertimbangkan untuk menerima *render prop* seperti `renderItem`. Di sini, `List` menerima `renderItem` sebagai *prop*. `List` memanggil `renderItem` untuk setiap item dan mengoper `isHighlighted` sebagai argumen:

```js {1,7}
export default function List({ items, renderItem }) {
Expand All @@ -259,7 +259,7 @@ export default function List({ items, renderItem }) {
})}
```

The `renderItem` prop is called a "render prop" because it's a prop that specifies how to render something. For example, you can pass a `renderItem` implementation that renders a `<Row>` with the given `isHighlighted` value:
*Prop* `renderItem` disebut "render prop" karena merupakan *prop* yang menentukan cara me-*render* sesuatu. Misalnya, Anda dapat mengoper `renderItem` yang me-*render* `<Row>` dengan nilai `isHighlighted` yang diberikan:

```js {3,7}
<List
Expand All @@ -274,7 +274,7 @@ The `renderItem` prop is called a "render prop" because it's a prop that specifi
/>
```

The end result is the same as with `cloneElement`:
Hasil akhirnya sama dengan `cloneElement`:

```js {4,8,12}
<List>
Expand All @@ -293,7 +293,7 @@ The end result is the same as with `cloneElement`:
</List>
```

However, you can clearly trace where the `isHighlighted` value is coming from.
Namun, Anda dapat dengan mudah melacak dari mana nilai `isHighlighted` berasal.

<Sandpack>

Expand Down Expand Up @@ -389,22 +389,21 @@ button {

</Sandpack>

This pattern is preferred to `cloneElement` because it is more explicit.
Pola ini lebih anjurkan daripada `cloneElement` karena lebih eksplisit.

---

### Passing data through context {/*passing-data-through-context*/}
### Mengoper data melalui context {/*passing-data-through-context*/}

Another alternative to `cloneElement` is to [pass data through context.](/learn/passing-data-deeply-with-context)
Alternatif lain untuk `cloneElement` adalah [mengoper data melalui *context*.](/learn/passing-data-deeply-with-context)


For example, you can call [`createContext`](/reference/react/createContext) to define a `HighlightContext`:
Sebagai contoh, Anda dapat memanggil [`createContext`](/reference/react/createContext) untuk mendefinisikan `HighlightContext`:

```js
export const HighlightContext = createContext(false);
```

Your `List` component can wrap every item it renders into a `HighlightContext` provider:
Komponen `List` dapat menggabungkan setiap item yang di-*render* ke dalam *provider* `HighlightContext`:

```js {8,10}
export default function List({ items, renderItem }) {
Expand All @@ -421,15 +420,15 @@ export default function List({ items, renderItem }) {
})}
```

With this approach, `Row` does not need to receive an `isHighlighted` prop at all. Instead, it reads the context:
Dengan pendekatan ini, `Row` tidak perlu menerima *prop* `isHighlighted` sama sekali. Sebaliknya, dengan membaca *context*-nya:

```js Row.js {2}
export default function Row({ title }) {
const isHighlighted = useContext(HighlightContext);
// ...
```

This allows the calling component to not know or worry about passing `isHighlighted` to `<Row>`:
Hal ini memungkinkan komponen pemanggil untuk tidak mengetahui atau peduli tentang pengoperan `isHighlighted` ke `<Row>`:

```js {4}
<List
Expand All @@ -440,7 +439,7 @@ This allows the calling component to not know or worry about passing `isHighligh
/>
```

Instead, `List` and `Row` coordinate the highlighting logic through context.
Sebagai gantinya, `List` dan `Row` mengoordinasikan logika penyorotan melalui *context*.

<Sandpack>

Expand Down Expand Up @@ -550,13 +549,13 @@ button {

</Sandpack>

[Learn more about passing data through context.](/reference/react/useContext#passing-data-deeply-into-the-tree)
[Pelajari lebih lanjut tentang mengoper data melalui *context*.](/reference/react/useContext#passing-data-deeply-into-the-tree)

---

### Extracting logic into a custom Hook {/*extracting-logic-into-a-custom-hook*/}
### Mengekstraksi logika ke dalam Hook kustom {/*extracting-logic-into-a-custom-hook*/}

Another approach you can try is to extract the "non-visual" logic into your own Hook, and use the information returned by your Hook to decide what to render. For example, you could write a `useList` custom Hook like this:
Pendekatan lain yang dapat Anda coba adalah mengekstrak logika "non-visual" ke dalam Hook Anda sendiri, dan menggunakan informasi yang dikembalikan oleh Hook Anda untuk memutuskan apa yang akan di-*render*. Misalnya, Anda dapat menulis Hook kustom `useList` seperti ini:

```js
import { useState } from 'react';
Expand All @@ -575,7 +574,7 @@ export default function useList(items) {
}
```

Then you could use it like this:
Lalu Anda dapat menggunakannya seperti ini:

```js {2,9,13}
export default function App() {
Expand All @@ -598,7 +597,7 @@ export default function App() {
}
```

The data flow is explicit, but the state is inside the `useList` custom Hook that you can use from any component:
Aliran datanya eksplisit, tetapi *state* ada di dalam Hook kustom `useList` yang dapat Anda gunakan dari komponen apa pun:

<Sandpack>

Expand Down Expand Up @@ -691,4 +690,4 @@ button {

</Sandpack>

This approach is particularly useful if you want to reuse this logic between different components.
Pendekatan ini sangat berguna jika Anda ingin menggunakan kembali logika ini di komponen yang berbeda.