diff --git a/content/docs/portals.md b/content/docs/portals.md index 650121396..bbc258d0e 100644 --- a/content/docs/portals.md +++ b/content/docs/portals.md @@ -1,24 +1,24 @@ --- id: portals -title: Portals +title: Portal permalink: docs/portals.html --- -Portals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component. +Portal menyediakan cara utama untuk me-*render* anak ke dalam simpul DOM yang berada di luar hierarki komponen induk. ```js ReactDOM.createPortal(child, container) ``` -The first argument (`child`) is any [renderable React child](/docs/react-component.html#render), such as an element, string, or fragment. The second argument (`container`) is a DOM element. +Argumen pertama (`child`) berupa [anak React yang bisa di-*render*](/docs/react-component.html#render), misalnya sebuah elemen, *string*, atau *fragment*. Argumen kedua (`container`) merupakan elemen DOM. -## Usage {#usage} +## Penggunaan {#usage} -Normally, when you return an element from a component's render method, it's mounted into the DOM as a child of the nearest parent node: +Umumnya saat Anda mengembalikan sebuah elemen dari *method* *render* komponen, elemen tersebut dipasang ke DOM sebagai anak pada simpul induk terdekat: ```js{4,6} render() { - // React mounts a new div and renders the children into it + // React memasang div baru dan me-render anaknya kepadanya return (
{this.props.children} @@ -27,12 +27,13 @@ render() { } ``` -However, sometimes it's useful to insert a child into a different location in the DOM: +Akan tetapi terkadang ada gunanya untuk menyisipkan sebuah anak ke lokasi yang berbeda dalam DOM: ```js{6} render() { - // React does *not* create a new div. It renders the children into `domNode`. - // `domNode` is any valid DOM node, regardless of its location in the DOM. + // React *tidak* membuat div baru. React me-render anak ke dalam `domNode`. + // `domNode` berupa simpul DOM apa saja yang valid, tidak tergantung pada + // lokasinya dalam DOM. return ReactDOM.createPortal( this.props.children, domNode @@ -40,21 +41,21 @@ render() { } ``` -A typical use case for portals is when a parent component has an `overflow: hidden` or `z-index` style, but you need the child to visually "break out" of its container. For example, dialogs, hovercards, and tooltips. +Penggunaan umum untuk portal adalah ketika komponen induk memiliki gaya `overflow: hidden` atau `z-index`, tetapi Anda harus "memisahkan" anak secara visual dari kontainernya. Misalnya pada dialog, *hovercard*, atau *tooltip*. -> Note: +> Catatan: > -> When working with portals, remember that [managing keyboard focus](/docs/accessibility.html#programmatically-managing-focus) becomes very important. +> Saat bekerja dengan portal, perhatikan bahwa [mengelola fokus papan ketik](/docs/accessibility.html#programmatically-managing-focus) menjadi sangat penting. > -> For modal dialogs, ensure that everyone can interact with them by following the [WAI-ARIA Modal Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal). +> Untuk dialog modal, pastikan semua pihak bisa berinteraksi dengannya dengan mengikuti [WAI-ARIA Modal Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.1/#dialog_modal). -[**Try it on CodePen**](https://codepen.io/gaearon/pen/yzMaBd) +[**Coba di CodePen**](https://codepen.io/gaearon/pen/yzMaBd) -## Event Bubbling Through Portals {#event-bubbling-through-portals} +## *Event Bubbling* lewat Portal {#event-bubbling-through-portals} -Even though a portal can be anywhere in the DOM tree, it behaves like a normal React child in every other way. Features like context work exactly the same regardless of whether the child is a portal, as the portal still exists in the *React tree* regardless of position in the *DOM tree*. +Walau sebuah portal bisa berada di mana saja dalam pohon DOM, portal tersebut berperilaku seperti halnya anak React yang normal. Fitur seperti *context* bekerja sama persis tanpa tergantung apakah sebuah anak adalah sebuah portal, karena portal masih berada dalam *pohon React* tanpa memandang posisinya dalam *pohon DOM*. -This includes event bubbling. An event fired from inside a portal will propagate to ancestors in the containing *React tree*, even if those elements are not ancestors in the *DOM tree*. Assuming the following HTML structure: +Ini mencakup *event bubbling*. Sebuah *event* yang dijalankan dari dalam portal akan dipropagasikan ke induknya dalam *pohon React* yang memuatnya, walau elemen tersebut bukan merupakan induk dalam *pohon DOM*. Misalnya pada struktur HTML berikut: ```html @@ -65,10 +66,10 @@ This includes event bubbling. An event fired from inside a portal will propagate ``` -A `Parent` component in `#app-root` would be able to catch an uncaught, bubbling event from the sibling node `#modal-root`. +Komponen `Parent` pada `#app-root` akan bisa menangkap *event bubbling* yang belum ditangkap dari simpul sederajat `#modal-root`. ```js{28-31,42-49,53,61-63,70-71,74} -// These two containers are siblings in the DOM +// Kedua kontainer berikut sederajat dalam DOM const appRoot = document.getElementById('app-root'); const modalRoot = document.getElementById('modal-root'); @@ -79,14 +80,14 @@ class Modal extends React.Component { } componentDidMount() { - // The portal element is inserted in the DOM tree after - // the Modal's children are mounted, meaning that children - // will be mounted on a detached DOM node. If a child - // component requires to be attached to the DOM tree - // immediately when mounted, for example to measure a - // DOM node, or uses 'autoFocus' in a descendant, add - // state to Modal and only render the children when Modal - // is inserted in the DOM tree. + // Elemen portal disisipkan dalam pohon DOM setelah + // anak dari Modal dipasang, yang berarti anak tersebut + // akan dipasang pada simpul DOM yang terpisah. Jika + // komponen anak harus disematkan ke dalam pohon DOM + // segera setelah dipasang, misalnya untuk mengukur dimensi + // simpul DOM, atau menggunakan 'autoFocus' pada turunannya, + // tambahkan state pada Modal dan hanya render para anak saat + // Modal disisipkan dalam pohon DOM. modalRoot.appendChild(this.el); } @@ -110,9 +111,9 @@ class Parent extends React.Component { } handleClick() { - // This will fire when the button in Child is clicked, - // updating Parent's state, even though button - // is not direct descendant in the DOM. + // Ini akan dijalankan ketika tombol pada Child diklik, + // memperbarui state Parent, walau tombol tersebut + // bukan turunan langsung dalam DOM. this.setState(state => ({ clicks: state.clicks + 1 })); @@ -121,12 +122,12 @@ class Parent extends React.Component { render() { return (
-

Number of clicks: {this.state.clicks}

+

Jumlah klik: {this.state.clicks}

- Open up the browser DevTools - to observe that the button - is not a child of the div - with the onClick handler. + Buka DevTools browser + untuk mengamati bahwa tombol + bukan anak dari div + pada handler onClick.

@@ -137,11 +138,11 @@ class Parent extends React.Component { } function Child() { - // The click event on this button will bubble up to parent, - // because there is no 'onClick' attribute defined + // Event klik pada tombol ini akan meluap ke induk, + // karena tidak ada atribut 'onClick' yang didefinisikan return (
- +
); } @@ -149,6 +150,6 @@ function Child() { ReactDOM.render(, appRoot); ``` -[**Try it on CodePen**](https://codepen.io/gaearon/pen/jGBWpE) +[**Coba di CodePen**](https://codepen.io/gaearon/pen/jGBWpE) -Catching an event bubbling up from a portal in a parent component allows the development of more flexible abstractions that are not inherently reliant on portals. For example, if you render a `` component, the parent can capture its events regardless of whether it's implemented using portals. +Menangkap *event bubbling* yang meluap dari portal pada komponen induk mengizinkan pengembangan abstraksi yang lebih fleksibel yang tidak mengandalkan portal. Misalnya jika Anda me-*render* komponen ``, induk bisa menangkap *event*-nya tanpa tergantung apakah diimplementasikan dengan portal atau tidak. diff --git a/content/docs/react-without-es6.md b/content/docs/react-without-es6.md index 8b54d0981..93d3426eb 100644 --- a/content/docs/react-without-es6.md +++ b/content/docs/react-without-es6.md @@ -1,36 +1,36 @@ --- id: react-without-es6 -title: React Without ES6 +title: React Tanpa ES6 permalink: docs/react-without-es6.html --- -Normally you would define a React component as a plain JavaScript class: +Umumnya Anda mendefinisikan komponen React sebagai kelas JavaScript biasa: ```javascript class Greeting extends React.Component { render() { - return

Hello, {this.props.name}

; + return

Halo {this.props.name}

; } } ``` -If you don't use ES6 yet, you may use the `create-react-class` module instead: +Jika Anda belum menggunakan ES6, Anda bisa menggunakan modul `create-react-class`: ```javascript var createReactClass = require('create-react-class'); var Greeting = createReactClass({ render: function() { - return

Hello, {this.props.name}

; + return

Halo {this.props.name}

; } }); ``` -The API of ES6 classes is similar to `createReactClass()` with a few exceptions. +API untuk kelas ES6 mirip dengan `createReactClass()`, dengan beberapa pengecualian. -## Declaring Default Props {#declaring-default-props} +## Mendeklarasikan *Props* *Default* {#declaring-default-props} -With functions and ES6 classes `defaultProps` is defined as a property on the component itself: +Dengan kelas dan fungsi ES6, `defaultProps` didefinisikan sebagai properti komponennya sendiri: ```javascript class Greeting extends React.Component { @@ -38,17 +38,17 @@ class Greeting extends React.Component { } Greeting.defaultProps = { - name: 'Mary' + name: 'Maria' }; ``` -With `createReactClass()`, you need to define `getDefaultProps()` as a function on the passed object: +Dengan `createReactClass()`, Anda harus mendefinisikan `getDefaultProps()` sebagai fungsi pada objek yang dioperkan: ```javascript var Greeting = createReactClass({ getDefaultProps: function() { return { - name: 'Mary' + name: 'Maria' }; }, @@ -57,9 +57,9 @@ var Greeting = createReactClass({ }); ``` -## Setting the Initial State {#setting-the-initial-state} +## Menyetel *State* Awal {#setting-the-initial-state} -In ES6 classes, you can define the initial state by assigning `this.state` in the constructor: +Pada kelas ES6, Anda bisa mendefinisikan *state* awal dengan menetapkan `this.state` pada konstruktor: ```javascript class Counter extends React.Component { @@ -71,7 +71,7 @@ class Counter extends React.Component { } ``` -With `createReactClass()`, you have to provide a separate `getInitialState` method that returns the initial state: +Dengan `createReactClass()`, Anda harus menyediakan *method* `getInitialState` terpisah yang mengembalikan *state* awal: ```javascript var Counter = createReactClass({ @@ -82,16 +82,16 @@ var Counter = createReactClass({ }); ``` -## Autobinding {#autobinding} +## *Autobinding* {#autobinding} -In React components declared as ES6 classes, methods follow the same semantics as regular ES6 classes. This means that they don't automatically bind `this` to the instance. You'll have to explicitly use `.bind(this)` in the constructor: +Pada komponen React yang dideklarasikan sebagai kelas ES6, *method* mengikuti semantik yang sama seperti kelas ES6 reguler. Ini berarti *method* tersebut tidak secara otomatis mem-*bind* `this` kepada *instance*. Anda harus secara eksplisit menggunakan `.bind(this)` pada konstruktor: ```javascript class SayHello extends React.Component { constructor(props) { super(props); - this.state = {message: 'Hello!'}; - // This line is important! + this.state = {message: 'Halo!'}; + // Baris berikut penting! this.handleClick = this.handleClick.bind(this); } @@ -100,22 +100,23 @@ class SayHello extends React.Component { } render() { - // Because `this.handleClick` is bound, we can use it as an event handler. + // Karena `this.handleClick` telah di-bind, kita bisa menggunakannya + // sebagai event handler. return ( ); } } ``` -With `createReactClass()`, this is not necessary because it binds all methods: +Dengan `createReactClass()`, hal tersebut tidak diperlukan karena semua *method* akan di-*bind*: ```javascript var SayHello = createReactClass({ getInitialState: function() { - return {message: 'Hello!'}; + return {message: 'Halo!'}; }, handleClick: function() { @@ -125,26 +126,26 @@ var SayHello = createReactClass({ render: function() { return ( ); } }); ``` -This means writing ES6 classes comes with a little more boilerplate code for event handlers, but the upside is slightly better performance in large applications. +Ini berarti penulisan dengan kelas ES6 disertai dengan kode *boilerplate* untuk *event handler* tetapi manfaatnya adalah kinerja yang sedikit lebih baik dalam aplikasi yang besar. -If the boilerplate code is too unattractive to you, you may enable the **experimental** [Class Properties](https://babeljs.io/docs/plugins/transform-class-properties/) syntax proposal with Babel: +Jika kode *boilerplate* sangat tidak menarik bagi Anda, Anda bisa mengaktifkan sintaksis [*Class Property*](https://babeljs.io/docs/plugins/transform-class-properties/) yang bersifat **eksperimental** dengan Babel: ```javascript class SayHello extends React.Component { constructor(props) { super(props); - this.state = {message: 'Hello!'}; + this.state = {message: 'Halo!'}; } - // WARNING: this syntax is experimental! - // Using an arrow here binds the method: + // PERINGATAN: sintaksis ini bersifat eksperimental! + // Menggunakan *arrow* akan mem-bind method: handleClick = () => { alert(this.state.message); } @@ -152,34 +153,34 @@ class SayHello extends React.Component { render() { return ( ); } } ``` -Please note that the syntax above is **experimental** and the syntax may change, or the proposal might not make it into the language. +Perhatikan bahwa sintaksis di atas bersifat **eksperimental** dan sintaksis mungkin akan berubah, atau proposal ini tidak akan disertakan dalam bahasa. -If you'd rather play it safe, you have a few options: +Jika Anda ingin bermain pada area yang aman, Anda memiliki beberapa opsi: -* Bind methods in the constructor. -* Use arrow functions, e.g. `onClick={(e) => this.handleClick(e)}`. -* Keep using `createReactClass`. +* Mem-*bind* *method* dalam konstruktor. +* Gunakan *arrow function*, misalnya `onClick={(e) => this.handleClick(e)}`. +* Terus gunakan `createReactClass`. -## Mixins {#mixins} +## Mixin {#mixins} ->**Note:** +>**Catatan:** > ->ES6 launched without any mixin support. Therefore, there is no support for mixins when you use React with ES6 classes. +>ES6 diluncurkan tanpa adanya dukungan *mixin*. Oleh sebab itu, tidak ada dukungan untuk *mixin* saat Anda menggunakan React dengan kelas ES6. > ->**We also found numerous issues in codebases using mixins, [and don't recommend using them in the new code](/blog/2016/07/13/mixins-considered-harmful.html).** +>**Kami juga menemukan banyak masalah pada basis kode yang menggunakan *mixin*, [dan tidak menyarankan untuk menggunakannya untuk kode yang baru](/blog/2016/07/13/mixins-considered-harmful.html).** > ->This section exists only for the reference. +>Bagian berikut hanya digunakan untuk rujukan. -Sometimes very different components may share some common functionality. These are sometimes called [cross-cutting concerns](https://en.wikipedia.org/wiki/Cross-cutting_concern). `createReactClass` lets you use a legacy `mixins` system for that. +Terkadang komponen yang sangat berbeda bisa berbagi fungsionalitas yang sama. Hal ini terkadang disebut sebagai [*cross-cutting concern*](https://en.wikipedia.org/wiki/Cross-cutting_concern). `createReactClass` memungkinkan Anda untuk menggunakan sistem `mixin` yang bersifat *legacy* untuk hal tersebut. -One common use case is a component wanting to update itself on a time interval. It's easy to use `setInterval()`, but it's important to cancel your interval when you don't need it anymore to save memory. React provides [lifecycle methods](/docs/react-component.html#the-component-lifecycle) that let you know when a component is about to be created or destroyed. Let's create a simple mixin that uses these methods to provide an easy `setInterval()` function that will automatically get cleaned up when your component is destroyed. +Salah satu kasus penggunaan yang umum adalah sebuah komponen ingin memperbarui dirinya sendiri secara periodik. Sangat mudah untuk menggunakan `setInterval()`, tetapi sangat penting untuk membatalkan interval jika Anda tidak membutuhkannya lagi untuk menghemat memori. React menyediakan [*lifecycle method*](/docs/react-component.html#the-component-lifecycle) yang bisa memberi tahu Anda kapan komponen akan diciptakan atau dihancurkan. Sebagai contoh, mari kita buat *mixin* yang sederhana yang menggunakan *method* berikut untuk menyediakan fungsi `setInterval()` yang mudah, yang akan dibersihkan secara otomatis ketika komponen Anda dihancurkan. ```javascript var SetIntervalMixin = { @@ -197,12 +198,12 @@ var SetIntervalMixin = { var createReactClass = require('create-react-class'); var TickTock = createReactClass({ - mixins: [SetIntervalMixin], // Use the mixin + mixins: [SetIntervalMixin], // Gunakan mixin getInitialState: function() { return {seconds: 0}; }, componentDidMount: function() { - this.setInterval(this.tick, 1000); // Call a method on the mixin + this.setInterval(this.tick, 1000); // Panggil method pada mixin }, tick: function() { this.setState({seconds: this.state.seconds + 1}); @@ -210,7 +211,7 @@ var TickTock = createReactClass({ render: function() { return (

- React has been running for {this.state.seconds} seconds. + React telah berjalan selama {this.state.seconds} detik.

); } @@ -222,4 +223,4 @@ ReactDOM.render( ); ``` -If a component is using multiple mixins and several mixins define the same lifecycle method (i.e. several mixins want to do some cleanup when the component is destroyed), all of the lifecycle methods are guaranteed to be called. Methods defined on mixins run in the order mixins were listed, followed by a method call on the component. +Jika komponen menggunakan beberapa *mixin* dan beberapa *mixin* mendefinisikan *lifecycle method* yang sama (contohnya, beberapa *mixin* ingin melakukan pembersihan ketika komponen dihancurkan), semua *lifecycle method* dijamin untuk dipanggil. *Method* yang didefinisikan pada *mixin* dijalankan secara berurutan sesuai dengan dengan proses pendaftarannya, diikuti dengan pemanggilan *method* pada komponen. diff --git a/content/docs/react-without-jsx.md b/content/docs/react-without-jsx.md index 85cdba45f..2999815a4 100644 --- a/content/docs/react-without-jsx.md +++ b/content/docs/react-without-jsx.md @@ -4,11 +4,11 @@ title: React Without JSX permalink: docs/react-without-jsx.html --- -JSX is not a requirement for using React. Using React without JSX is especially convenient when you don't want to set up compilation in your build environment. +JSX bukan persyaratan untuk menggunakan React. Menggunakan React tanpa JSX sangat cocok ketika Anda tidak ingin mengatur kompilasi di *build environment* Anda. -Each JSX element is just syntactic sugar for calling `React.createElement(component, props, ...children)`. So, anything you can do with JSX can also be done with just plain JavaScript. +Setiap elemen hanyalah _syntactic sugar_ untuk pemanggilan `React.createElement(component, props, ...children)`. Jadi, apa pun yang dapat Anda lakukan dengan JSX juga dapat dilakukan hanya dengan JavaScript biasa. -For example, this code written with JSX: +Misalnya, kode yang ditulis dengan JSX berikut: ```js class Hello extends React.Component { @@ -23,7 +23,7 @@ ReactDOM.render( ); ``` -can be compiled to this code that does not use JSX: +Dapat dikompilasi dengan kode dibawah ini untuk yang tidak menggunakan JSX: ```js class Hello extends React.Component { @@ -38,11 +38,11 @@ ReactDOM.render( ); ``` -If you're curious to see more examples of how JSX is converted to JavaScript, you can try out [the online Babel compiler](babel://jsx-simple-example). +Jika Anda ingin tahu lebih lanjut untuk melihat banyak contoh tentang bagaimana JSX dikonversi ke JavaScript, Anda dapat mencobanya di [the online Babel compiler](babel://jsx-simple-example). -The component can either be provided as a string, or as a subclass of `React.Component`, or a plain function for stateless components. +Komponen dapat diberikan sebagai _string_, atau sebagai subkelas dari `React.Component`, atau fungsi murni untuk komponen _stateless_. -If you get tired of typing `React.createElement` so much, one common pattern is to assign a shorthand: +Jika Anda terlalu lelah mengetik `React.createElement` satu pola umum adalah dengan menggunakan pintasan: ```js const e = React.createElement; @@ -53,7 +53,7 @@ ReactDOM.render( ); ``` -If you use this shorthand form for `React.createElement`, it can be almost as convenient to use React without JSX. +Jika Anda menggunakan pintasan `React.createElement`, akan lebih mudah menggunakan React tanpa JSX. -Alternatively, you can refer to community projects such as [`react-hyperscript`](https://github.com/mlmorg/react-hyperscript) and [`hyperscript-helpers`](https://github.com/ohanhi/hyperscript-helpers) which offer a terser syntax. +Atau, Anda dapat merujuk ke proyek komunitas seperti [`react-hyperscript`](https://github.com/mlmorg/react-hyperscript) dan[`hyperscript-helpers`](https://github.com/ohanhi/hyperscript-helpers) yang menawarkan _terser syntax_. diff --git a/content/docs/reference-test-renderer.md b/content/docs/reference-test-renderer.md index 89312ca8c..f41025b21 100644 --- a/content/docs/reference-test-renderer.md +++ b/content/docs/reference-test-renderer.md @@ -6,20 +6,21 @@ layout: docs category: Reference --- -**Importing** +**Cara Import** ```javascript import TestRenderer from 'react-test-renderer'; // ES6 -const TestRenderer = require('react-test-renderer'); // ES5 with npm +const TestRenderer = require('react-test-renderer'); // ES5 dengan npm ``` -## Overview {#overview} +## Ikhtisar {#overview} -This package provides a React renderer that can be used to render React components to pure JavaScript objects, without depending on the DOM or a native mobile environment. -Essentially, this package makes it easy to grab a snapshot of the platform view hierarchy (similar to a DOM tree) rendered by a React DOM or React Native component without using a browser or [jsdom](https://github.com/tmpvar/jsdom). +*Package* ini menyediakan *renderer* React yang dapat digunakan untuk me-*render* komponen React menjadi objek JavaScript murni, tanpa bergantung pada DOM atau bahasa *native* pada telepon seluler. -Example: +Pada dasarnya, *package* ini memberi kemudahan untuk mengambil *snapshot* dari hierarki tampilan *platform* (mirip dengan pohon DOM) yang di-*render* oleh React DOM atau komponen React Native tanpa menggunakan *browser* atau [jsdom](https://github.com/tmpvar/jsdom). + +Contoh: ```javascript import TestRenderer from 'react-test-renderer'; @@ -38,9 +39,9 @@ console.log(testRenderer.toJSON()); // children: [ 'Facebook' ] } ``` -You can use Jest's snapshot testing feature to automatically save a copy of the JSON tree to a file and check in your tests that it hasn't changed: [Learn more about it](https://jestjs.io/docs/en/snapshot-testing). +Anda dapat menggunakan fitur *snapshot testing* dari Jest untuk menyimpan salinan pohon JSON ke *file* secara otomatis dan melakukan pengecekan di tes anda terhadap adanya perubahan (struktur): [Pelajari lebih lanjut](http://facebook.github.io/jest/blog/2016/07/27/jest-14.html). -You can also traverse the output to find specific nodes and make assertions about them. +Anda juga dapat melintasi ke bagian keluaran untuk menemukan *node* tertentu dan membuat perbandingan terhadap *node-node* tersebut. ```javascript import TestRenderer from 'react-test-renderer'; @@ -49,7 +50,7 @@ function MyComponent() { return (
-

Hello

+

Halo

) } @@ -95,7 +96,7 @@ expect(testInstance.findByProps({className: "sub"}).children).toEqual(['Sub']); * [`testInstance.parent`](#testinstanceparent) * [`testInstance.children`](#testinstancechildren) -## Reference {#reference} +## Referensi {#reference} ### `TestRenderer.create()` {#testrenderercreate} @@ -103,7 +104,7 @@ expect(testInstance.findByProps({className: "sub"}).children).toEqual(['Sub']); TestRenderer.create(element, options); ``` -Create a `TestRenderer` instance with the passed React element. It doesn't use the real DOM, but it still fully renders the component tree into memory so you can make assertions about it. Returns a [TestRenderer instance](#testrenderer-instance). +Membuat *instance* `TestRenderer` dengan mengoper elemen React. Fungsi ini tidak menggunakan DOM asli, tetapi masih sepenuhnya me-*render* diagram komponen ke dalam memori sehingga Anda masih dapat membandingkannya. Mengembalikan sebuah [*instance* TestRenderer](#testrenderer-instance). ### `TestRenderer.act()` {#testrendereract} @@ -111,27 +112,27 @@ Create a `TestRenderer` instance with the passed React element. It doesn't use t TestRenderer.act(callback); ``` -Similar to the [`act()` helper from `react-dom/test-utils`](/docs/test-utils.html#act), `TestRenderer.act` prepares a component for assertions. Use this version of `act()` to wrap calls to `TestRenderer.create` and `testRenderer.update`. +Mirip seperti [fungsi pembantu `act()` dari `react-dom/test-utils`](/docs/test-utils.html#act), `TestRenderer.act` menyiapkan komponen untuk dibandingkan. Gunakan versi `act()` ini untuk membungkus panggilan ke `TestRenderer.create` dan `testRenderer.update`. ```javascript import {create, act} from 'react-test-renderer'; -import App from './app.js'; // The component being tested +import App from './app.js'; // Komponen yang akan dites -// render the component +// merender komponen let root; act(() => { root = create() }); -// make assertions on root +// membuat perbandingan dengan root expect(root.toJSON()).toMatchSnapshot(); -// update with some different props +// memperbarui dengan prop berbeda act(() => { root = root.update(); }) -// make assertions on root +// membuat perbandingan dengan root expect(root.toJSON()).toMatchSnapshot(); ``` @@ -141,7 +142,7 @@ expect(root.toJSON()).toMatchSnapshot(); testRenderer.toJSON() ``` -Return an object representing the rendered tree. This tree only contains the platform-specific nodes like `
` or `` and their props, but doesn't contain any user-written components. This is handy for [snapshot testing](https://facebook.github.io/jest/docs/en/snapshot-testing.html#snapshot-testing-with-jest). +Menghasilkan objek yang merepresentasikan pohon yang telah di-*render*. Pohon ini hanya berisi *node* pada *platform* spesifik seperti `
` atau `` dan beserta *props*-nya, tetapi tidak mengandung komponen yang dibuat oleh pengguna. Hal ini berguna untuk [*snapshot testing*](http://facebook.github.io/jest/docs/en/snapshot-testing.html#snapshot-testing-with-jest). ### `testRenderer.toTree()` {#testrenderertotree} @@ -149,7 +150,7 @@ Return an object representing the rendered tree. This tree only contains the pla testRenderer.toTree() ``` -Return an object representing the rendered tree. The representation is more detailed than the one provided by `toJSON()`, and includes the user-written components. You probably don't need this method unless you're writing your own assertion library on top of the test renderer. +Menghasilkan objek yang merepresentasikan pohon yang telah di-*render*. Tidak seperti `toJSON ()`, representasinya lebih detail daripada yang dihasilkan oleh `toJSON ()`, dan termasuk komponen yang dibuat pengguna. Anda mungkin tidak memerlukan *method* ini kecuali Anda sedang membuat *library* perbandingan sendiri di atas *test renderer*. ### `testRenderer.update()` {#testrendererupdate} @@ -157,7 +158,7 @@ Return an object representing the rendered tree. The representation is more deta testRenderer.update(element) ``` -Re-render the in-memory tree with a new root element. This simulates a React update at the root. If the new element has the same type and key as the previous element, the tree will be updated; otherwise, it will re-mount a new tree. +Me-*render* ulang pohon dalam memori dengan elemen *root* baru. Hal Ini mensimulasikan pembaruan React di *root*. Jika elemen baru memiliki tipe dan *key* yang sama dengan elemen sebelumnya, struktur pohon akan diperbarui; jika tidak, akan memasang ulang pohon yang baru. ### `testRenderer.unmount()` {#testrendererunmount} @@ -165,7 +166,7 @@ Re-render the in-memory tree with a new root element. This simulates a React upd testRenderer.unmount() ``` -Unmount the in-memory tree, triggering the appropriate lifecycle events. +Melepas pohon dalam memori, memicu siklus hidup *event* yang sesuai. ### `testRenderer.getInstance()` {#testrenderergetinstance} @@ -173,7 +174,7 @@ Unmount the in-memory tree, triggering the appropriate lifecycle events. testRenderer.getInstance() ``` -Return the instance corresponding to the root element, if available. This will not work if the root element is a function component because they don't have instances. +Menghasilkan *instance* yang sesuai dengan elemen *root*, jika tersedia. Hal ini tidak akan berfungsi jika elemen *root* adalah *function component*, karena *function component* tidak memiliki *instance*. ### `testRenderer.root` {#testrendererroot} @@ -181,7 +182,7 @@ Return the instance corresponding to the root element, if available. This will n testRenderer.root ``` -Returns the root "test instance" object that is useful for making assertions about specific nodes in the tree. You can use it to find other "test instances" deeper below. +Menghasilkan objek *root* "*test instance*" yang berguna untuk membuat pernyataan tentang *node* tertentu di pohon. Anda dapat menggunakannya untuk menemukan "*test instance*" lainnya secara lebih dalam di bawah ini. ### `testInstance.find()` {#testinstancefind} @@ -189,7 +190,7 @@ Returns the root "test instance" object that is useful for making assertions abo testInstance.find(test) ``` -Find a single descendant test instance for which `test(testInstance)` returns `true`. If `test(testInstance)` does not return `true` for exactly one test instance, it will throw an error. +Menemukan turunan tunggal *test instance* yang mana `test(testInstance)` menghasilkan nilai `true`. Jika `test(testInstance)` tidak menghasilkan nilai `true` untuk satu *test instance*, fungsi ini akan melemparkan *error*. ### `testInstance.findByType()` {#testinstancefindbytype} @@ -197,7 +198,7 @@ Find a single descendant test instance for which `test(testInstance)` returns `t testInstance.findByType(type) ``` -Find a single descendant test instance with the provided `type`. If there is not exactly one test instance with the provided `type`, it will throw an error. +Menemukan turunan tunggal dari *test instance* berdasarkan `type` yang disediakan. Jika tidak ada satupun *test instance* dengan `type` yang disediakan, fungsi ini akan melemparkan *error*. ### `testInstance.findByProps()` {#testinstancefindbyprops} @@ -205,7 +206,7 @@ Find a single descendant test instance with the provided `type`. If there is not testInstance.findByProps(props) ``` -Find a single descendant test instance with the provided `props`. If there is not exactly one test instance with the provided `props`, it will throw an error. +Menemukan turunan tunggal dari *test instance* berdasarkan `props` yang disediakan. Jika tidak ada satupun *test instance* dengan `props` yang disediakan, fungsi ini akan melemparkan *error*. ### `testInstance.findAll()` {#testinstancefindall} @@ -213,7 +214,7 @@ Find a single descendant test instance with the provided `props`. If there is no testInstance.findAll(test) ``` -Find all descendant test instances for which `test(testInstance)` returns `true`. +Menemukan semua turunan *test instance* dimana `test(testInstance)` menghasilkan nilai `true`. ### `testInstance.findAllByType()` {#testinstancefindallbytype} @@ -221,7 +222,7 @@ Find all descendant test instances for which `test(testInstance)` returns `true` testInstance.findAllByType(type) ``` -Find all descendant test instances with the provided `type`. +Menemukan semua turunan dari *test instance* berdasarkan `type` yang disediakan. ### `testInstance.findAllByProps()` {#testinstancefindallbyprops} @@ -229,7 +230,7 @@ Find all descendant test instances with the provided `type`. testInstance.findAllByProps(props) ``` -Find all descendant test instances with the provided `props`. +Menemukan semua turunan dari *test instance* berdasarkan `props` yang disediakan. ### `testInstance.instance` {#testinstanceinstance} @@ -237,7 +238,7 @@ Find all descendant test instances with the provided `props`. testInstance.instance ``` -The component instance corresponding to this test instance. It is only available for class components, as function components don't have instances. It matches the `this` value inside the given component. +*Instance* komponen bersangkutan dari *test instance* ini. Hanya tersedia untuk *class component*, karena *function component* tidak memiliki *instance*. Bernilai sama dengan nilai `this` di dalam komponen yang diberikan. ### `testInstance.type` {#testinstancetype} @@ -245,7 +246,7 @@ The component instance corresponding to this test instance. It is only available testInstance.type ``` -The component type corresponding to this test instance. For example, a `
@@ -189,25 +189,25 @@ function CustomTextInput(props) { } ``` -### Exposing DOM Refs to Parent Components {#exposing-dom-refs-to-parent-components} +### Mengekspos *Ref* DOM ke Komponen Induk {#exposing-dom-refs-to-parent-components} -In rare cases, you might want to have access to a child's DOM node from a parent component. This is generally not recommended because it breaks component encapsulation, but it can occasionally be useful for triggering focus or measuring the size or position of a child DOM node. +Pada sebagian kecil kasus, Anda mungkin ingin mendapatkan akses ke simpul DOM anak dari komponen induk. Hal ini tidak disarankan karena akan merusak enkapsulasi komponen, tetapi terkadang berguna untuk memicu fokus atau mengukur ukuran atau posisi simpul DOM anak. -While you could [add a ref to the child component](#adding-a-ref-to-a-class-component), this is not an ideal solution, as you would only get a component instance rather than a DOM node. Additionally, this wouldn't work with function components. +Walau Anda bisa [menambahkan *ref* ke *child component*](#adding-a-ref-to-a-class-component), ini bukan solusi yang ideal, karena Anda hanya akan mendapatkan instans komponen, bukan simpul DOM. Selain itu, hal ini tidak akan berfungsi dengan *function component*. -If you use React 16.3 or higher, we recommend to use [ref forwarding](/docs/forwarding-refs.html) for these cases. **Ref forwarding lets components opt into exposing any child component's ref as their own**. You can find a detailed example of how to expose a child's DOM node to a parent component [in the ref forwarding documentation](/docs/forwarding-refs.html#forwarding-refs-to-dom-components). +Jika Anda menggunakan React 16.3 atau yang lebih baru, kami sarankan untuk menggunakan [*ref forwarding*](/docs/forwarding-refs.html) untuk kasus semacam ini. ***Ref forwarding* memungkinkan komponen untuk memilih untuk mengekspos semua *ref* komponen anak sebagai miliknya sendiri**. Anda bisa menemukan contoh mendetail tentang cara mengekspos simpul DOM anak ke komponen induk [dalam dokumentasi *ref forwarding*](/docs/forwarding-refs.html#forwarding-refs-to-dom-components). -If you use React 16.2 or lower, or if you need more flexibility than provided by ref forwarding, you can use [this alternative approach](https://gist.github.com/gaearon/1a018a023347fe1c2476073330cc5509) and explicitly pass a ref as a differently named prop. +Jika Anda menggunakan React 16.2 atau yang lebih lawas, atau jika Anda membutuhkan lebih banyak fleksibilitas dibandingkan dengan yang disediakan oleh *ref forwarding*, Anda bisa menggunakan [pendekatan alternatif ini](https://gist.github.com/gaearon/1a018a023347fe1c2476073330cc5509) dan secara eksplisit mengoper sebuah *ref* sebagai *props* dengan nama yang berbeda. -When possible, we advise against exposing DOM nodes, but it can be a useful escape hatch. Note that this approach requires you to add some code to the child component. If you have absolutely no control over the child component implementation, your last option is to use [`findDOMNode()`](/docs/react-dom.html#finddomnode), but it is discouraged and deprecated in [`StrictMode`](/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage). +Jika dimungkinkan, kami sarankan untuk tidak mengekspos simpul DOM, walau bisa berguna sebagai jalan keluar. Perhatikan bahwa pendekatan ini membutuhkan tambahan kode pada komponen anak Jika Anda sama sekali tidak memiliki kontrol pada implementasi komponen anak, opsi terakhir Anda adalah menggunakan [`findDOMNode()`](/docs/react-dom.html#finddomnode). Tetapi hal ini tidak disarankan dan akan menjadi *deprecated* dalam [`StrictMode`](/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage). -### Callback Refs {#callback-refs} +### *Callback Ref* {#callback-refs} -React also supports another way to set refs called "callback refs", which gives more fine-grain control over when refs are set and unset. +React juga mendukung cara lain untuk menetapkan *ref* yang disebut sebagai *"callback ref"*, yang memberikan kontrol lebih mendetail kapan *ref* akan di-*set* dan di-*unset*. -Instead of passing a `ref` attribute created by `createRef()`, you pass a function. The function receives the React component instance or HTML DOM element as its argument, which can be stored and accessed elsewhere. +Alih-alih mengoper atribut `ref` yang dibuat oleh `createRef()`, Anda mengoper sebuah fungsi. Fungsi tersebut menerima instans komponen React atau elemen DOM HTML sebagai argumennya, yang bisa disimpan dan diakses di tempat lain. -The example below implements a common pattern: using the `ref` callback to store a reference to a DOM node in an instance property. +Contoh berikut mengimplementasikan sebuah pola umum: menggunakan *callback* `ref` untuk menyimpan rujukan ke simpul DOM dalam properti instans. ```javascript{5,7-9,11-14,19,29,34} class CustomTextInput extends React.Component { @@ -221,19 +221,19 @@ class CustomTextInput extends React.Component { }; this.focusTextInput = () => { - // Focus the text input using the raw DOM API + // Fokus pada input teks menggunakan API DOM dasar if (this.textInput) this.textInput.focus(); }; } componentDidMount() { - // autofocus the input on mount + // autofocus pada input saat mount this.focusTextInput(); } render() { - // Use the `ref` callback to store a reference to the text input DOM - // element in an instance field (for example, this.textInput). + // Gunakan callback `ref` untuk menyimpan rujukan ke elemen DOM + // input teks dalam field instans (misalnya, this.textInput). return (
@@ -251,9 +251,9 @@ class CustomTextInput extends React.Component { } ``` -React will call the `ref` callback with the DOM element when the component mounts, and call it with `null` when it unmounts. Refs are guaranteed to be up-to-date before `componentDidMount` or `componentDidUpdate` fires. +React akan memanggil *callback* `ref` dengan elemen DOM saat komponen dipasang dan memanggilnya dengan `null` saat dilepas. *Ref* dijamin untuk selalu diperbarui sebelum `componentDidMount` atau `componentDidUpdate` dijalankan. -You can pass callback refs between components like you can with object refs that were created with `React.createRef()`. +Anda bisa mengoper *callback ref* antarkomponen seperti halnya yang bisa Anda lakukan dengan *object ref* yang dibuat dengan `React.createRef()`. ```javascript{4,13} function CustomTextInput(props) { @@ -275,16 +275,16 @@ class Parent extends React.Component { } ``` -In the example above, `Parent` passes its ref callback as an `inputRef` prop to the `CustomTextInput`, and the `CustomTextInput` passes the same function as a special `ref` attribute to the ``. As a result, `this.inputElement` in `Parent` will be set to the DOM node corresponding to the `` element in the `CustomTextInput`. +Pada contoh di atas, `Parent` mengoper *callback ref*-nya sebagai *props* `inputRef` kepada `CustomTextInput` dan `CustomTextInput` mengoper fungsi yang sama sebagai atribut `ref` khusus kepada ``. Hasilnya, `this.inputElement` pada `Parent` akan disetel ke simpul DOM yang sesuai dengan elemen `` pada `CustomTextInput`. -### Legacy API: String Refs {#legacy-api-string-refs} +### API *Legacy*: *String Ref* {#legacy-api-string-refs} -If you worked with React before, you might be familiar with an older API where the `ref` attribute is a string, like `"textInput"`, and the DOM node is accessed as `this.refs.textInput`. We advise against it because string refs have [some issues](https://github.com/facebook/react/pull/8333#issuecomment-271648615), are considered legacy, and **are likely to be removed in one of the future releases**. +Jika sebelumnya Anda bekerja dengan React, Anda mungkin sudah mengenal API lawas dengan atribut `ref` berupa *string*, misalnya `"textInput"`, dan simpul DOM yang diakses dengan `this.refs.textInput`. Kami sarankan untuk tidak melakukannya karena *string ref* memiliki [beberapa masalah](https://github.com/facebook/react/pull/8333#issuecomment-271648615) dan dipertimbangkan sebagai *legacy*, serta **kemungkinan besar akan dihapus dalam salah satu rilis di masa mendatang**. -> Note +> Catatan > -> If you're currently using `this.refs.textInput` to access refs, we recommend using either the [callback pattern](#callback-refs) or the [`createRef` API](#creating-refs) instead. +> Jika saat ini Anda menggunakan `this.refs.textInput` untuk mengakses *ref*, kami sarankan untuk beralih menggunakan [*callback pattern*](#callback-refs) atau [API `createRef`](#creating-refs). -### Caveats with callback refs {#caveats-with-callback-refs} +### Kekurangan pada *callback ref* {#caveats-with-callback-refs} -If the `ref` callback is defined as an inline function, it will get called twice during updates, first with `null` and then again with the DOM element. This is because a new instance of the function is created with each render, so React needs to clear the old ref and set up the new one. You can avoid this by defining the `ref` callback as a bound method on the class, but note that it shouldn't matter in most cases. +Jika *callback* `ref` didefinisikan sebagai fungsi *inline*, fungsi ini akan dipanggil dua kali dalam proses pembaruan, yang pertama dengan argumen `null`, yang kedua dengan argumen elemen DOM. Ini terjadi karena instans baru dari fungsi akan dibuat dalam setiap proses *render*, karena React harus membersihkan *ref* yang lama dan menyiapkan yang baru. Anda bisa menghindari hal ini dengan mendefinisikan *callback* `ref` sebagau *bound method* pada kelas, tetapi perhatikan bahwa dalam sebagian besar kasus hal ini tidak berpengaruh. diff --git a/content/docs/static-type-checking.md b/content/docs/static-type-checking.md index ed35a9503..606b91e16 100644 --- a/content/docs/static-type-checking.md +++ b/content/docs/static-type-checking.md @@ -1,42 +1,42 @@ --- id: static-type-checking -title: Static Type Checking +title: Pengecekan Static Type permalink: docs/static-type-checking.html --- -Static type checkers like [Flow](https://flow.org/) and [TypeScript](https://www.typescriptlang.org/) identify certain types of problems before you even run your code. They can also improve developer workflow by adding features like auto-completion. For this reason, we recommend using Flow or TypeScript instead of `PropTypes` for larger code bases. +Pengecekan *static type* seperti [Flow](https://flow.org/) dan [TypeScript](https://www.typescriptlang.org/) mengidentifikasi jenis masalah tertentu bahkan sebelum kode dijalankan. Pengecekan tersebut juga bisa meningkatkan alur kerja pengembang dengan menambahkan fitur seperti pelengkapan kode secara otomatis. Dengan alasan ini, kami sarankan untuk menggunakan Flow atau TypeScript alih-alih menggunakan `PropTypes` untuk kode program berukuran besar. ## Flow {#flow} -[Flow](https://flow.org/) is a static type checker for your JavaScript code. It is developed at Facebook and is often used with React. It lets you annotate the variables, functions, and React components with a special type syntax, and catch mistakes early. You can read an [introduction to Flow](https://flow.org/en/docs/getting-started/) to learn its basics. +[Flow](https://flow.org/) merupakan pengecek *static type* untuk kode JavaScript. Pengecek ini dikembangkan di Facebook dan sering digunakan bersama React. Pengecek ini memungkinkan Anda untuk menganotasi variabel, fungsi, dan komponen React menggunakan sintaksis khusus dan menemukan kesalahan secara dini. Anda bisa membaca [pengenalan Flow](https://flow.org/en/docs/getting-started/) untuk mempelajari dasar-dasarnya. -To use Flow, you need to: +Untuk menggunakannya, Anda harus: -* Add Flow to your project as a dependency. -* Ensure that Flow syntax is stripped from the compiled code. -* Add type annotations and run Flow to check them. +* Menambahkan Flow ke proyek Anda sebagai *dependency*. +* Memastikan sintaksis Flow dihapus dari kode hasil dikompilasi. +* Menambahkan *type annotation* dan menjalankan Flow untuk mengeceknya. -We will explain these steps below in detail. +Kami akan menjelaskan langkah-langkah tersebut secara mendetail. -### Adding Flow to a Project {#adding-flow-to-a-project} +### Menambahkan Flow ke Proyek {#adding-flow-to-a-project} -First, navigate to your project directory in the terminal. You will need to run the following command: +Pertama-tama, buka direktori proyek Anda di terminal. Anda akan harus menjalankan perintah berikut: -If you use [Yarn](https://yarnpkg.com/), run: +Jika menggunakan [Yarn](https://yarnpkg.com/), jalankan: ```bash yarn add --dev flow-bin ``` -If you use [npm](https://www.npmjs.com/), run: +Jika menggunakan [npm](https://www.npmjs.com/), jalankan: ```bash npm install --save-dev flow-bin ``` -This command installs the latest version of Flow into your project. +Perintah tersebut akan menginstal versi terbaru Flow ke proyek Anda. -Now, add `flow` to the `"scripts"` section of your `package.json` to be able to use this from the terminal: +Kini, tambahkan `flow` ke bagian `"scripts"` pada `package.json` Anda untuk bisa menjalankannya dari terminal: ```js{4} { @@ -49,53 +49,53 @@ Now, add `flow` to the `"scripts"` section of your `package.json` to be able to } ``` -Finally, run one of the following commands: +Terakhir, jalankan salah satu dari perintah berikut: -If you use [Yarn](https://yarnpkg.com/), run: +Jika menggunakan [Yarn](https://yarnpkg.com/), jalankan: ```bash yarn run flow init ``` -If you use [npm](https://www.npmjs.com/), run: +Jika menggunakan [npm](https://www.npmjs.com/), jalankan: ```bash npm run flow init ``` -This command will create a Flow configuration file that you will need to commit. +Perintah tersebut akan membuat konfigurasi Flow yang harus Anda sertakan dalam *commit*. -### Stripping Flow Syntax from the Compiled Code {#stripping-flow-syntax-from-the-compiled-code} +### Menghapus Sintaksis Flow dari Kode Hasil Kompilasi {#stripping-flow-syntax-from-the-compiled-code} -Flow extends the JavaScript language with a special syntax for type annotations. However, browsers aren't aware of this syntax, so we need to make sure it doesn't end up in the compiled JavaScript bundle that is sent to the browser. +Flow memperluas bahasa JavaScript dengan sintaksis khusus untuk *type annotation*. Akan tetapi *browser* tidak mengenal sintaksis ini, jadi kita harus memastikan sintaksis tersebut dihapus dari bundel JavaScript hasil kompilasi yang akan dikirim ke *browser*. -The exact way to do this depends on the tools you use to compile JavaScript. +Cara yang benar untuk melakukannya tergantung pada peralatan yang Anda gunakan untuk mengompilasi JavaScript. #### Create React App {#create-react-app} -If your project was set up using [Create React App](https://github.com/facebookincubator/create-react-app), congratulations! The Flow annotations are already being stripped by default so you don't need to do anything else in this step. +Jika proyek Anda disiapkan menggunakan [Create React App](https://github.com/facebookincubator/create-react-app), maka kami ucapkan selamat! Anotasi Flow akan dihapus secara *default* dan tidak ada yang perlu dilakukan pada langkah ini. #### Babel {#babel} ->Note: +>Catatan: > ->These instructions are *not* for Create React App users. Even though Create React App uses Babel under the hood, it is already configured to understand Flow. Only follow this step if you *don't* use Create React App. +>Petunjuk berikut *bukan* ditujukan untuk pengguna Create React App. Walau pengguna Create React App menggunakan Babel di balik layar, Babel tersebut telah dikonfigurasi untuk memahami Flow. Hanya ikuti langkah berikut jika Anda *tidak* menggunakan Create React App. -If you manually configured Babel for your project, you will need to install a special preset for Flow. +Jika Babel dikonfigurasi secara manual untuk proyek Anda, Anda harus menginstal *preset* khusus untuk Flow. -If you use Yarn, run: +Jika menggunakan Yarn, jalankan: ```bash yarn add --dev @babel/preset-flow ``` -If you use npm, run: +Jika menggunakan npm, jalankan: ```bash npm install --save-dev @babel/preset-flow ``` -Then add the `flow` preset to your [Babel configuration](https://babeljs.io/docs/usage/babelrc/). For example, if you configure Babel through `.babelrc` file, it could look like this: +Kemudian tambahkan *preset* `flow` ke [konfigurasi Babel](https://babeljs.io/docs/usage/babelrc/) Anda. Misalnya, jika Babel dikonfigurasi lewat *file* `.babelrc`, tampilannya mungkin seperti berikut: ```js{3} { @@ -106,101 +106,101 @@ Then add the `flow` preset to your [Babel configuration](https://babeljs.io/docs } ``` -This will let you use the Flow syntax in your code. +Ini memungkinkan Anda untuk menggunakan sintaksis Flow pada kode Anda. ->Note: +>Catatan: > ->Flow does not require the `react` preset, but they are often used together. Flow itself understands JSX syntax out of the box. +>Flow tidak membutuhkan *preset* `react`, tetapi keduanya sering digunakan secara bersama. Flow sendiri memahami sintaksis JSX secara mandiri. -#### Other Build Setups {#other-build-setups} +#### *Setup Build* Lainnya {#other-build-setups} -If you don't use either Create React App or Babel, you can use [flow-remove-types](https://github.com/flowtype/flow-remove-types) to strip the type annotations. +Jika Anda tidak menggunakan *Create React App* atau Babel, Anda bisa menggunakan [flow-remove-types](https://github.com/flowtype/flow-remove-types) untuk menghapus *type annotation*. -### Running Flow {#running-flow} +### Menjalankan Flow {#running-flow} -If you followed the instructions above, you should be able to run Flow for the first time. +Jika Anda mengikuti petunjuk di atas, Anda bisa menjalankan Flow pertama kali. ```bash yarn flow ``` -If you use npm, run: +Jika menggunakan npm, jalankan: ```bash npm run flow ``` -You should see a message like: +Seharusnya Anda akan melihat pesan seperti: ``` No errors! ✨ Done in 0.17s. ``` -### Adding Flow Type Annotations {#adding-flow-type-annotations} +### Menambahkan *Type Annotation* Flow {#adding-flow-type-annotations} -By default, Flow only checks the files that include this annotation: +Secara default, Flow hanya mengecek *file* yang disertakan anotasi berikut: ```js // @flow ``` -Typically it is placed at the top of a file. Try adding it to some files in your project and run `yarn flow` or `npm run flow` to see if Flow already found any issues. +Umumnya anotasi tersebut ditempatkan di bagian atas *file*. Coba tambahkan anotasi tersebut ke beberapa *file* dalam proyek dan jalankan `yarn flow` atau `npm run flow` untuk melihat apakah Flow sudah menemukan masalah. -There is also [an option](https://flow.org/en/docs/config/options/#toc-all-boolean) to force Flow to check *all* files regardless of the annotation. This can be too noisy for existing projects, but is reasonable for a new project if you want to fully type it with Flow. +Tersedia juga [sebuah *opsi*](https://flow.org/en/docs/config/options/#toc-all-boolean) untuk memaksa Flow untuk mengecek *semua* *file* tanpa melihat adanya anotasi. Ini bisa berakibat terlalu "ramai" untuk proyek yang sudah ada, tetapi cukup bagi proyek baru jika Anda ingin menggunakan Flow secara lengkap. -Now you're all set! We recommend to check out the following resources to learn more about Flow: +Kini Anda sudah siap! Kami sarankan untuk memeriksa sumber daya berikut untuk mempelajari lebih lanjut tentang Flow: -* [Flow Documentation: Type Annotations](https://flow.org/en/docs/types/) -* [Flow Documentation: Editors](https://flow.org/en/docs/editors/) -* [Flow Documentation: React](https://flow.org/en/docs/react/) -* [Linting in Flow](https://medium.com/flow-type/linting-in-flow-7709d7a7e969) +* [Dokumentasi Flow: *Type Annotation*](https://flow.org/en/docs/types/) +* [Dokumentasi Flow: Editor](https://flow.org/en/docs/editors/) +* [Dokumentasi Flow: React](https://flow.org/en/docs/react/) +* [*Linting* dalam Flow](https://medium.com/flow-type/linting-in-flow-7709d7a7e969) ## TypeScript {#typescript} -[TypeScript](https://www.typescriptlang.org/) is a programming language developed by Microsoft. It is a typed superset of JavaScript, and includes its own compiler. Being a typed language, TypeScript can catch errors and bugs at build time, long before your app goes live. You can learn more about using TypeScript with React [here](https://github.com/Microsoft/TypeScript-React-Starter#typescript-react-starter). +[TypeScript](https://www.typescriptlang.org/) merupakan bahasa pemrograman yang dikembangkan oleh Microsoft. Bahasa ini merupakan *superset* dari JavaScript dan menyertakan kompilernya sendiri. Oleh karena TypeScript adalah *typed language*, bahasa ini bisa menangkap kesalahan dan *bug* pada saat proses *build*, jauh sebelum aplikasi Anda tampil untuk para pemirsa. Anda bisa mempelajari lebih lanjut tentang penggunaan TypeScript dengan React [di sini](https://github.com/Microsoft/TypeScript-React-Starter#typescript-react-starter). -To use TypeScript, you need to: -* Add TypeScript as a dependency to your project -* Configure the TypeScript compiler options -* Use the right file extensions -* Add definitions for libraries you use +Untuk menggunakan TypeScript, Anda harus: +* Menambahkan TypeScript sebagai *dependency* ke proyek Anda +* Mengonfigurasi opsi kompiler TypeScript +* Menggunakan ektensi *file* yang benar +* Menambahkan definisi untuk *library* yang Anda gunakan -Let's go over these in detail. +Mari kita jelajahi secara mendetail. -### Using TypeScript with Create React App {#using-typescript-with-create-react-app} +### Menggunakan TypeScript dengan *Create React App* {#using-typescript-with-create-react-app} -Create React App supports TypeScript out of the box. +*Create React App* mendukung TypeScript secara langsung. -To create a **new project** with TypeScript support, run: +Untuk membuat **proyek baru** dengan dukungan TypeScript, jalankan: ```bash npx create-react-app my-app --typescript ``` -You can also add it to an **existing Create React App project**, [as documented here](https://facebook.github.io/create-react-app/docs/adding-typescript). +Anda juga bisa menambahkan TypeScript ke **proyek *Create React App* yang sudah ada**, [seperti yang didokumentasikan di sini](https://facebook.github.io/create-react-app/docs/adding-typescript). ->Note: +>Catatan: > ->If you use Create React App, you can **skip the rest of this page**. It describes the manual setup which doesn't apply to Create React App users. +>Jika Anda menggunakan *Create React App*, Anda bisa melewati **sisa halaman ini**. Sisa halaman ini menjelaskan penyiapan manual yang tidak berlaku untuk pengguna *Create React App*. -### Adding TypeScript to a Project {#adding-typescript-to-a-project} -It all begins with running one command in your terminal. +### Menambahkan TypeScript ke Proyek {#adding-typescript-to-a-project} +Semuanya dimulai dengan menjalankan satu perintah di terminal Anda. -If you use [Yarn](https://yarnpkg.com/), run: +Jika menggunakan [Yarn](https://yarnpkg.com/), jalankan: ```bash yarn add --dev typescript ``` -If you use [npm](https://www.npmjs.com/), run: +Jika menggunakan [npm](https://www.npmjs.com/), jalankan: ```bash npm install --save-dev typescript ``` -Congrats! You've installed the latest version of TypeScript into your project. Installing TypeScript gives us access to the `tsc` command. Before configuration, let's add `tsc` to the "scripts" section in our `package.json`: +Selamat! Anda telah menginstal versi terbaru TypeScript ke proyek Anda. Instalasi TypeScript memberikan akses ke perintah `tsc`. Sebelum mengonfigurasi, mari tambahkan `tsc` ke bagian "scripts" pada `package.json`: ```js{4} { @@ -213,27 +213,27 @@ Congrats! You've installed the latest version of TypeScript into your project. I } ``` -### Configuring the TypeScript Compiler {#configuring-the-typescript-compiler} -The compiler is of no help to us until we tell it what to do. In TypeScript, these rules are defined in a special file called `tsconfig.json`. To generate this file: +### Mengonfigurasi Kompiler TypeScript {#configuring-the-typescript-compiler} +Kompiler tidak akan membantu kita hingga kita memberi tahu apa yang harus kompiler lakukan. Pada TypeScript, aturan ini didefinisikan pada berkas khusus yang diberi nama `tsconfig.json`. Untuk membuat berkas ini: -If you use [Yarn](https://yarnpkg.com/), run: +Jika menggunakan [Yarn](https://yarnpkg.com/), jalankan: ```bash yarn run tsc --init ``` -If you use [npm](https://www.npmjs.com/), run: +Jika menggunakan [npm](https://www.npmjs.com/), jalankan: ```bash npx tsc --init ``` -Looking at the now generated `tsconfig.json`, you can see that there are many options you can use to configure the compiler. For a detailed description of all the options, check [here](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html). +Pada `tsconfig.json` yang baru dibuat, Anda bisa melihat banyak opsi yang bisa dikonfigurasi untuk kompiler. Untuk deskripsi mendetail tentang semua opsi kunjungi [halaman ini](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html). -Of the many options, we'll look at `rootDir` and `outDir`. In its true fashion, the compiler will take in typescript files and generate javascript files. However we don't want to get confused with our source files and the generated output. +Dari sekian banyak opsi, mari kita lihat opsi `rootDir` dan `outDir`. Awalnya, kompiler akan mengambil berkas TypeScript dan menciptakan berkas JavaScript. Akan tetapi kita tidak ingin mencampur aduk berkas sumber dengan berkas keluaran yang diciptakan. -We'll address this in two steps: -* Firstly, let's arrange our project structure like this. We'll place all our source code in the `src` directory. +Kita akan mengatasi masalah ini dalam dua langkah: +* Pertama-tama, mari kita susun struktur proyek kita seperti berikut. Kita akan tempatkan semua kode sumber dalam direktori `src`. ``` ├── package.json @@ -242,7 +242,7 @@ We'll address this in two steps: └── tsconfig.json ``` -* Next, we'll tell the compiler where our source code is and where the output should go. +* Berikutnya, kita akan memberi tahu kompiler letak kode sumber kita dan tempat keluaran akan disimpan. ```js{6,7} // tsconfig.json @@ -257,40 +257,41 @@ We'll address this in two steps: } ``` -Great! Now when we run our build script the compiler will output the generated javascript to the `build` folder. The [TypeScript React Starter](https://github.com/Microsoft/TypeScript-React-Starter/blob/master/tsconfig.json) provides a `tsconfig.json` with a good set of rules to get you started. +Kini, jika kita menjalankan *build script*, maka kompiler akan menghasilkan kode JavaScript di *folder* `build`. [TypeScript React Starter](https://github.com/Microsoft/TypeScript-React-Starter/blob/master/tsconfig.json) menyediakan `tsconfig.json` dengan sekumpulan aturan yang cukup bagi Anda untuk memulai. -Generally, you don't want to keep the generated javascript in your source control, so be sure to add the build folder to your `.gitignore`. +Secara umum Anda tidak ingin menyimpan kode JavaScript yang dihasilkan dalam sistem *source control* Anda, jadi pastikan untuk menambahkan *folder* *build* ke *file* `.gitignore`. -### File extensions {#file-extensions} -In React, you most likely write your components in a `.js` file. In TypeScript we have 2 file extensions: +### Ekstensi *file* {#file-extensions} +Dalam React, kemungkinan besar Anda menulis komponen pada *file* `.js`. Dalam TypeScript kita memiliki 2 ekstensi *file*: -`.ts` is the default file extension while `.tsx` is a special extension used for files which contain `JSX`. +* `.ts` sebagai ekstensi *default*, dan +* `.tsx` yang merupakan ekstensi khusus yang digunakan untuk file yang mengandung `JSX`. -### Running TypeScript {#running-typescript} +### Menjalankan TypeScript {#running-typescript} -If you followed the instructions above, you should be able to run TypeScript for the first time. +Jika Anda mengikuti petunjuk di atas, seharusnya Anda bisa menjalankan TypeScript untuk pertama kali. ```bash yarn build ``` -If you use npm, run: +Jika menggunakan npm, jalankan: ```bash npm run build ``` -If you see no output, it means that it completed successfully. +Jika tidak melihat keluaran, berarti prosesnya selesai dengan sukses. -### Type Definitions {#type-definitions} -To be able to show errors and hints from other packages, the compiler relies on declaration files. A declaration file provides all the type information about a library. This enables us to use javascript libraries like those on npm in our project. +### *Type Definition* {#type-definitions} +Untuk bisa melihat kesalahan dan petunjuk dari *package* lainnya, kompiler mengandalkan *file* deklarasi. *File* deklarasi menyediakan seluruh informasi *type* tentang sebuah *library*. Ini memungkinkan kita untuk menggunakan *library* JavaScript, misalnya dari npm, dalam proyek kita. -There are two main ways to get declarations for a library: +Ada dua cara utama untuk mendapatkan deklarasi sebuah *library*: -__Bundled__ - The library bundles its own declaration file. This is great for us, since all we need to do is install the library, and we can use it right away. To check if a library has bundled types, look for an `index.d.ts` file in the project. Some libraries will have it specified in their `package.json` under the `typings` or `types` field. +__Dibundel__ - *Library* membundel *file* deklarasinya sendiri. Ini baik sekali bagi kita, karena yang perlu kita lakukan adalah menginstal *library* tersebut, dan kita bisa langsung menggunakannya. Untuk memeriksa apakah *library* memiliki *type* yang dibundel, cari *file* bernama `index.d.ts` dalam proyeknya. Beberapa *library* menentukannya dalam *file* `package.json` mereka, di bawah *field* `typings` atau `types`. -__[DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped)__ - DefinitelyTyped is a huge repository of declarations for libraries that don't bundle a declaration file. The declarations are crowd-sourced and managed by Microsoft and open source contributors. React for example doesn't bundle its own declaration file. Instead we can get it from DefinitelyTyped. To do so enter this command in your terminal. +__[DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped)__ - DefinitelyTyped adalah repositori raksasa berisi deklarasi *library* yang tidak membundel *file* deklarasi. Deklarasi di dalamnya diurun daya berbagai pihak dan dikelola oleh Microsoft beserta kontributor sumber terbuka. React misalnya, tidak membundel *file* deklarasinya sendiri, namun kita bisa mendapatkannya dari DefinitelyTyped. Untuk melakukannya, masukkan perintah berikut dalam terminal. ```bash # yarn @@ -300,8 +301,8 @@ yarn add --dev @types/react npm i --save-dev @types/react ``` -__Local Declarations__ -Sometimes the package that you want to use doesn't bundle declarations nor is it available on DefinitelyTyped. In that case, we can have a local declaration file. To do this, create a `declarations.d.ts` file in the root of your source directory. A simple declaration could look like this: +__Deklarasi Lokal__ +Terkadang *package* yang ingin digunakan tidak memiliki deklarasi terbundel atau tidak tersedia di DefinitelyTyped. Pada kasus ini, kita bisa membuat berkas deklarasi lokal. Untuk melakukannya, buat berkas `declarations.d.ts` pada akar direktori sumber Anda. Deklarasi sederhana tampak sebagai berikut: ```typescript declare module 'querystring' { @@ -310,24 +311,24 @@ declare module 'querystring' { } ``` -You are now ready to code! We recommend to check out the following resources to learn more about TypeScript: +Kini Anda siap menciptakan kode program! Kami sarankan untuk mengunjungi sumber daya berikut untuk mempelajari lebih lanjut tentang TypeScript: -* [TypeScript Documentation: Basic Types](https://www.typescriptlang.org/docs/handbook/basic-types.html) -* [TypeScript Documentation: Migrating from Javascript](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html) -* [TypeScript Documentation: React and Webpack](https://www.typescriptlang.org/docs/handbook/react-&-webpack.html) +* [Dokumentasi TypeScript: *Type* Dasar](https://www.typescriptlang.org/docs/handbook/basic-types.html) +* [Dokumentasi TypeScript: Migrasi dari Javascript](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html) +* [Dokumentasi TypeScript: React dan Webpack](https://www.typescriptlang.org/docs/handbook/react-&-webpack.html) ## Reason {#reason} -[Reason](https://reasonml.github.io/) is not a new language; it's a new syntax and toolchain powered by the battle-tested language, [OCaml](https://ocaml.org/). Reason gives OCaml a familiar syntax geared toward JavaScript programmers, and caters to the existing NPM/Yarn workflow folks already know. +[Reason](https://reasonml.github.io/) bukan sebuah bahasa baru, Reason merupakan sintaksis dan *toolchain* baru yang didukung bahasa [OCaml](https://ocaml.org/) yang telah teruji. Reason memberikan sintaksis OCaml yang familier, yang ditujukan untuk pemrogram JavaScript, serta melayani alur kerja NPM/Yarn yang sudah ada dan telah diketahui. -Reason is developed at Facebook, and is used in some of its products like Messenger. It is still somewhat experimental but it has [dedicated React bindings](https://reasonml.github.io/reason-react/) maintained by Facebook and a [vibrant community](https://reasonml.github.io/docs/en/community.html). +Reason dikembangkan di Facebook, dan digunakan dalam beberapa produknya seperti Messenger. Reason masih bersifat eksperimental tetapi telah memiliki [*binding* React khusus](https://reasonml.github.io/reason-react/) yang diasuh oleh Facebook serta [komunitas yang dinamis](https://reasonml.github.io/docs/en/community.html). ## Kotlin {#kotlin} -[Kotlin](https://kotlinlang.org/) is a statically typed language developed by JetBrains. Its target platforms include the JVM, Android, LLVM, and [JavaScript](https://kotlinlang.org/docs/reference/js-overview.html). +[Kotlin](https://kotlinlang.org/) merupakan *typed language* yang statis dan dikembangkan oleh JetBrains. Platform targetnya mencakup JVM, Android, LLVM, dan [JavaScript](https://kotlinlang.org/docs/reference/js-overview.html). -JetBrains develops and maintains several tools specifically for the React community: [React bindings](https://github.com/JetBrains/kotlin-wrappers) as well as [Create React Kotlin App](https://github.com/JetBrains/create-react-kotlin-app). The latter helps you start building React apps with Kotlin with no build configuration. +JetBrains mengembangkan dan mengasuh beberapa peralatan khusus untuk komunitas React: [*binding* React](https://github.com/JetBrains/kotlin-wrappers) serta [*Create React Kotlin App*](https://github.com/JetBrains/create-react-kotlin-app). Yang terakhir bisa membantu Anda membangun aplikasi React bersama Kotlin tanpa adanya konfigurasi *build*. -## Other Languages {#other-languages} +## Bahasa Lainnya {#other-languages} -Note there are other statically typed languages that compile to JavaScript and are thus React compatible. For example, [F#/Fable](https://fable.io/) with [elmish-react](https://elmish.github.io/react). Check out their respective sites for more information, and feel free to add more statically typed languages that work with React to this page! +Perhatikan bahwa ada beberapa *typed language* yang statis yang mengompilasi menjadi JavaScript serta kompatibel dengan React. Misalnya, [F#/Fable](https://fable.io/) dengan [elmish-react](https://elmish.github.io/react). Kunjungi masing-masing situs untuk informasi lebih lanjut. Silakan tambahkan *typed language* statis yang berfungsi bersama React ke halaman ini. diff --git a/content/docs/uncontrolled-components.md b/content/docs/uncontrolled-components.md index 54b729e96..2eeae22cc 100644 --- a/content/docs/uncontrolled-components.md +++ b/content/docs/uncontrolled-components.md @@ -1,14 +1,14 @@ --- id: uncontrolled-components -title: Uncontrolled Components +title: Uncontrolled Component permalink: docs/uncontrolled-components.html --- -In most cases, we recommend using [controlled components](/docs/forms.html#controlled-components) to implement forms. In a controlled component, form data is handled by a React component. The alternative is uncontrolled components, where form data is handled by the DOM itself. +Pada sebagian besar kasus, kami sarankan untuk menggunakan [*controlled component*](/docs/forms.html) untuk mengimpementasikan *form*. Pada *controlled component*, data *form* ditangani oleh komponen React. Cara alternatifnya adalah menggunakan *uncontrolled component*, di mana data *form* akan ditangani oleh DOM-nya sendiri. -To write an uncontrolled component, instead of writing an event handler for every state update, you can [use a ref](/docs/refs-and-the-dom.html) to get form values from the DOM. +Untuk menulis *uncontrolled component*, alih-alih menulis *event handler* untuk setiap pembaruan *state*, Anda bisa [menggunakan *ref*](/docs/refs-and-the-dom.html) untuk mendapatkan nilai *form* dari DOM. -For example, this code accepts a single name in an uncontrolled component: +Misalnya, kode berikut menerima sebuah nama dari sebuah *uncontrolled component*: ```javascript{5,9,18} class NameForm extends React.Component { @@ -19,7 +19,7 @@ class NameForm extends React.Component { } handleSubmit(event) { - alert('A name was submitted: ' + this.input.current.value); + alert('Sebuah nama telah dikirim: ' + this.input.current.value); event.preventDefault(); } @@ -27,56 +27,56 @@ class NameForm extends React.Component { return (
- +
); } } ``` -[**Try it on CodePen**](https://codepen.io/gaearon/pen/WooRWa?editors=0010) +[**Coba di CodePen**](https://codepen.io/gaearon/pen/WooRWa?editors=0010) -Since an uncontrolled component keeps the source of truth in the DOM, it is sometimes easier to integrate React and non-React code when using uncontrolled components. It can also be slightly less code if you want to be quick and dirty. Otherwise, you should usually use controlled components. +Oleh karena *uncontrolled component* menyimpan sumber kebenaran dalam DOM, terkadang lebih mudah untuk mengintegrasikan kode React dan non-React jika menggunakan *uncontrolled component*. Ini juga berarti lebih sedikit kode jika Anda menginginkan solusi cepat walau tak rapi. Selain itu pada umumnya Anda harus menggunakan *controlled component*. -If it's still not clear which type of component you should use for a particular situation, you might find [this article on controlled versus uncontrolled inputs](https://goshakkk.name/controlled-vs-uncontrolled-inputs-react/) to be helpful. +Jika masih belum jelas jenis komponen mana yang harus Anda gunakan untuk situasi tertentu, mungkin [artikel tentang *controlled input* versus *uncontrolled input*](https://goshakkk.name/controlled-vs-uncontrolled-inputs-react/) bisa membantu. -### Default Values {#default-values} +### Nilai Default {#default-values} -In the React rendering lifecycle, the `value` attribute on form elements will override the value in the DOM. With an uncontrolled component, you often want React to specify the initial value, but leave subsequent updates uncontrolled. To handle this case, you can specify a `defaultValue` attribute instead of `value`. +Pada *lifecycle rendering* React, atribut `value` pada elemen *form* akan menimpa nilai pada DOM. Dengan *uncontrolled component*, sering kali Anda menginginkan React untuk menentukan nilai awal tetapi pembaruan berikutnya dilakukan secara *uncontrolled*. Untuk menangani kasus ini, Anda bisa menentukan atribut `defaultValue` alih-alih menggunakan `value`. ```javascript{7} render() { return (
- +
); } ``` -Likewise, `` and `` support `defaultChecked`, and `