You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -215,13 +215,13 @@ Tentu saja, dua versi dari sebuah diagram komponen me-_render_ *di waktu yang sa
215
215
216
216
API seperti `useTransition` memungkinkan Anda untuk berfokus kepada _user experience_ yang diinginkan, dan tidak terlalu memikirkan teknis implementasinya. Namun membayangkan perubahan yang dibungkus dalam `startTransition` terjadi "di dalam branch" atau "di dunia lain" tetap menjadi metafor yang membantu.
217
217
218
-
### Transitions Are Everywhere {#transitions-are-everywhere}
218
+
### Transisi di Setiap Tempat {#transitions-are-everywhere}
219
219
220
-
As we learned from the [Suspense walkthrough](/docs/concurrent-mode-suspense.html), any component can "suspend" any time if some data it needs is not ready yet. We can strategically place`<Suspense>`boundaries in different parts of the tree to handle this, but it won't always be enough.
220
+
Seperti yang telah kita pelajari di [_walkthrough_ Suspense](/docs/concurrent-mode-suspense.html), setiap komponen dapat "menunda" setiap waktu ketika data yang diperlukan belum tersedia. Kita dapat menempatkan batas-batas`<Suspense>`secara strategis di tempat-tempat berbeda dalam diagram komponen untuk menangani ini, namun cara ini tidak selalu cukup.
221
221
222
-
Let's get back to our [first Suspense demo](https://codesandbox.io/s/frosty-hermann-bztrp)where there was just one profile. Currently, it fetches the data only once. We'll add a "Refresh" button to check for server updates.
222
+
Mari kita kembali ke [demo pertama Suspense](https://codesandbox.io/s/frosty-hermann-bztrp)ketika hanya ada satu profil pengguna. Saat ini, komponen ini hanya menarik data sekali. Kita ingin menambahkan tombol "Refresh" untuk mengecek perubahan dari peladen.
223
223
224
-
Our first attempt might look like this:
224
+
Percobaan pertama kita mungkin terlihat seperti ini:
225
225
226
226
```js{6-8,13-15}
227
227
const initialResource = fetchUserAndPosts();
@@ -247,13 +247,13 @@ function ProfilePage() {
247
247
}
248
248
```
249
249
250
-
**[Try it on CodeSandbox](https://codesandbox.io/s/boring-shadow-100tf)**
250
+
**[Coba di CodeSandbox](https://codesandbox.io/s/boring-shadow-100tf)**
251
251
252
-
In this example, we start data fetching at the load *and* every time you press "Refresh". We put the result of calling `fetchUserAndPosts()`into state so that components below can start reading the new data from the request we just kicked off.
252
+
Dalam contoh ini, kita memulai penarikan data di saat memuat *dan* setiap kali Anda menekan "Refresh". Kita menaruh hasil panggilan `fetchUserAndPosts()`ke dalam _state_ sehingga komponen-komponen di bawahnya dapat memulai membaca data baru dari _request_ yang kita baru jalankan.
253
253
254
-
We can see in [this example](https://codesandbox.io/s/boring-shadow-100tf)that pressing "Refresh" works. The`<ProfileDetails>`and`<ProfileTimeline>`components receive a new `resource`prop that represents the fresh data, they "suspend" because we don't have a response yet, and we see the fallbacks. When the response loads, we can see the updated posts (our fake API adds them every 3 seconds).
254
+
Kita dapat melihat [di contoh ini](https://codesandbox.io/s/boring-shadow-100tf)bahwa menekan tombol "Refresh" berhasil. Komponen`<ProfileDetails>`dan`<ProfileTimeline>`menerima _props_`resource`baru yang merepresentasikan data baru, komponen-komponen ini "menunda" perunahan karena kita belum mendapatkan _response_, dan kita dapat melihat kondisi _fallback_. Ketika _response_ telah dimuat, kita dapat melihat daftar postingan yang diperbarui (API tiruan kita menambahkannya setiap 3 detik).
255
255
256
-
However, the experience feels really jarring. We were browsing a page, but it got replaced by a loading state right as we were interacting with it. It's disorienting. **Just like before, to avoid showing an undesirable loading state, we can wrap the state update in a transition:**
256
+
Namun, pengalaman pengguna akan menjadi tidak enak. Ketika kita sedang _browsing_ sebuah halaman, namun tiba-tiba seluruh halaman diubah menjadi _state_loading sesaat sebelum kita akan berinteraksi dengannya, akan terasa membingungkan. **Seperti sebelumnya, untuk menghindari menampilkan _state__loading_ yang tidak diinginkan, kita dapat membungkus perubahan _state_ di dalam transisi:**
257
257
258
258
```js{2-5,9-11,21}
259
259
function ProfilePage() {
@@ -286,15 +286,15 @@ function ProfilePage() {
286
286
}
287
287
```
288
288
289
-
**[Try it on CodeSandbox](https://codesandbox.io/s/sleepy-field-mohzb)**
289
+
**[Coba di CodeSandbox](https://codesandbox.io/s/sleepy-field-mohzb)**
290
290
291
-
This feels a lot better! Clicking "Refresh" doesn't pull us away from the page we're browsing anymore. We see something is loading "inline", and when the data is ready, it's displayed.
291
+
Ini terasa lebih baik! Menekan tombol "Refresh" tidak akan menarik kita keluar dari halaman yang sedang kita liihat. Kita melihat sesuatu sedang dimuat secara "inline", dan ketika data telah siap, baru ditampilkan.
292
292
293
-
### Baking Transitions Into the Design System {#baking-transitions-into-the-design-system}
293
+
### Memadukan Transisi ke Dalam Design System {#baking-transitions-into-the-design-system}
294
294
295
-
We can now see that the need for `useTransition`is *very* common. Pretty much any button click or interaction that can lead to a component suspending needs to be wrapped in `useTransition`to avoid accidentally hiding something the user is interacting with.
295
+
Kita dapat melihat bahwa penggunaan `useTransition`sudah *sangat* diperlukan. Setiap tekanan tombol atau interaksi yang memerlukan penundaan komponen perlu dibungkus di dalam `useTransition`untuk menghindari menyembunyikan sesuatu yang pengguna sedang berinteraksi secara tidak sengaja.
296
296
297
-
This can lead to a lot of repetitive code across components. This is why **we generally recommend to bake`useTransition`into the *design system*components of your app**. For example, we can extract the transition logic into our own `<Button>`component:
297
+
Ini dapat mengasilkan penggunaan kode yang repetitif di berbagai komponen. Inilah kenapa **secara umum kita perlu memadukan`useTransition`ke dalam komponen *design system*di dalam aplikasi kita**. Sebagai contoh, kita dapat mengekstrak logika transisi ke dalam komponen `<Button>`kita:
298
298
299
299
```js{7-9,20,24}
300
300
function Button({ children, onClick }) {
@@ -326,9 +326,9 @@ function Button({ children, onClick }) {
326
326
}
327
327
```
328
328
329
-
**[Try it on CodeSandbox](https://codesandbox.io/s/modest-ritchie-iufrh)**
329
+
**[Coba di CodeSandbox](https://codesandbox.io/s/modest-ritchie-iufrh)**
330
330
331
-
Note that the button doesn't care *what* state we're updating. It's wrapping *any* state updates that happen during its `onClick`handler into a transition. Now that our `<Button>`takes care of setting up the transition, the`<ProfilePage>`component doesn't need to set up its own:
331
+
Perlu dicatat bahwa tombol ini tidak memperdulikan _state__apa_ yang kita ubah. Ia membungkus perubahan _state__apapun_ yang terjadi di dalam _handler_`onClick`ke dalam sebuah transisi. Karena `<Button>`sekarang yang melakukan pembuatan transisi, komponen`<ProfilePage>`tidak perlu membuatnya sendiri:
332
332
333
333
```js{4-6,11-13}
334
334
function ProfilePage() {
@@ -352,11 +352,11 @@ function ProfilePage() {
352
352
}
353
353
```
354
354
355
-
**[Try it on CodeSandbox](https://codesandbox.io/s/modest-ritchie-iufrh)**
355
+
**[Coba di CodeSandbox](https://codesandbox.io/s/modest-ritchie-iufrh)**
356
356
357
-
When a button gets clicked, it starts a transition and calls`props.onClick()`inside of it -- which triggers`handleRefreshClick`in the `<ProfilePage>` component. We start fetching the fresh data, but it doesn't trigger a fallback because we're inside a transition, and the 10 second timeout specified in the `useTransition`call hasn't passed yet. While a transition is pending, the button displays an inline loading indicator.
357
+
Ketika tombol diklik, ia akan memulai transisi dan memanggil`props.onClick()`di dalamnya -- yang memanggil`handleRefreshClick`di dalam komponen `<ProfilePage>`. Kita memulai menarik data yang baru, tapi tidak memanggil _fallback_ karena kita di dalam sebuah transisi, dan _timeout_ dengan durasi 10 detik yang dispesifikasikan di dalam panggilan `useTransition`belum terlewat. Ketika transisi sedang menunggu, tombol akan menunjukkan indikator _loading_ secara _inline_.
358
358
359
-
We can see now how Concurrent Mode helps us achieve a good user experience without sacrificing isolation and modularity of components. React coordinates the transition.
359
+
Kita dapat melihat bagaimana mode Concurrent membantu kita mendapatkan pengalaman pengguna yang baik tanpa mengorbankan isolasi dan modularitas dari komponen. React mengkoordinasikan transisinya.
360
360
361
361
## The Three Steps {#the-three-steps}
362
362
@@ -504,7 +504,7 @@ function ProfileTrivia({ resource }) {
504
504
}
505
505
```
506
506
507
-
**[Try it on CodeSandbox](https://codesandbox.io/s/focused-mountain-uhkzg)**
507
+
**[Coba di CodeSandbox](https://codesandbox.io/s/focused-mountain-uhkzg)**
508
508
509
509
If you press "Open Profile" now, you can tell something is wrong. It takes a whole seven seconds to make the transition now! This is because our trivia API is too slow. Let's say we can't make the API faster. How can we improve the user experience with this constraint?
510
510
@@ -528,7 +528,7 @@ function ProfilePage({ resource }) {
528
528
}
529
529
```
530
530
531
-
**[Try it on CodeSandbox](https://codesandbox.io/s/condescending-shape-s6694)**
531
+
**[Coba di CodeSandbox](https://codesandbox.io/s/condescending-shape-s6694)**
532
532
533
533
This reveals an important insight. React always prefers to go to the Skeleton state as soon as possible. Even if we use transitions with long timeouts everywhere, React will not stay in the Pending state for longer than necessary to avoid the Receded state.
534
534
@@ -563,7 +563,7 @@ function Button({ children, onClick }) {
563
563
}
564
564
```
565
565
566
-
**[Try it on CodeSandbox](https://codesandbox.io/s/floral-thunder-iy826)**
566
+
**[Coba di CodeSandbox](https://codesandbox.io/s/floral-thunder-iy826)**
567
567
568
568
This signals to the user that some work is happening. However, if the transition is relatively short (less than 500ms), it might be too distracting and make the transition itself feel *slower*.
569
569
@@ -597,7 +597,7 @@ return (
597
597
);
598
598
```
599
599
600
-
**[Try it on CodeSandbox](https://codesandbox.io/s/gallant-spence-l6wbk)**
600
+
**[Coba di CodeSandbox](https://codesandbox.io/s/gallant-spence-l6wbk)**
601
601
602
602
With this change, even though we're in the Pending state, we don't display any indication to the user until 500ms has passed. This may not seem like much of an improvement when the API responses are slow. But compare how it feels [before](https://codesandbox.io/s/thirsty-liskov-1ygph) and [after](https://codesandbox.io/s/hardcore-http-s18xr) when the API call is fast. Even though the rest of the code hasn't changed, suppressing a "too fast" loading state improves the perceived performance by not calling attention to the delay.
603
603
@@ -657,7 +657,7 @@ function Translation({ resource }) {
657
657
}
658
658
```
659
659
660
-
**[Try it on CodeSandbox](https://codesandbox.io/s/brave-villani-ypxvf)**
660
+
**[Coba di CodeSandbox](https://codesandbox.io/s/brave-villani-ypxvf)**
661
661
662
662
Notice how when you type into the input, the `<Translation>` component suspends, and we see the `<p>Loading...</p>` fallback until we get fresh results. This is not ideal. It would be better if we could see the *previous* translation for a bit while we're fetching the next one.
663
663
@@ -694,7 +694,7 @@ function App() {
694
694
}
695
695
```
696
696
697
-
**[Try it on CodeSandbox](https://codesandbox.io/s/zen-keldysh-rifos)**
697
+
**[Coba di CodeSandbox](https://codesandbox.io/s/zen-keldysh-rifos)**
698
698
699
699
Try typing into the input now. Something's wrong! The input is updating very slowly.
700
700
@@ -720,7 +720,7 @@ function handleChange(e) {
720
720
}
721
721
```
722
722
723
-
**[Try it on CodeSandbox](https://codesandbox.io/s/lively-smoke-fdf93)**
723
+
**[Coba di CodeSandbox](https://codesandbox.io/s/lively-smoke-fdf93)**
724
724
725
725
With this change, it works as expected. We can type into the input immediately, and the translation later "catches up" to what we have typed.
726
726
@@ -785,7 +785,7 @@ function ProfileTimeline({ isStale, resource }) {
785
785
}
786
786
```
787
787
788
-
**[Try it on CodeSandbox](https://codesandbox.io/s/vigorous-keller-3ed2b)**
788
+
**[Coba di CodeSandbox](https://codesandbox.io/s/vigorous-keller-3ed2b)**
789
789
790
790
The tradeoff we're making here is that `<ProfileTimeline>` will be inconsistent with other components and potentially show an older item. Click "Next" a few times, and you'll notice it. But thanks to that, we were able to cut down the transition time from 1000ms to 300ms.
791
791
@@ -816,7 +816,7 @@ function App() {
816
816
}
817
817
```
818
818
819
-
**[Try it on CodeSandbox](https://codesandbox.io/s/pensive-shirley-wkp46)**
819
+
**[Coba di CodeSandbox](https://codesandbox.io/s/pensive-shirley-wkp46)**
820
820
821
821
In this example, **every item in `<MySlowList>` has an artificial slowdown -- each of them blocks the thread for a few milliseconds**. We'd never do this in a real app, but this helps us simulate what can happen in a deep component tree with no single obvious place to optimize.
822
822
@@ -846,7 +846,7 @@ function App() {
846
846
}
847
847
```
848
848
849
-
**[Try it on CodeSandbox](https://codesandbox.io/s/infallible-dewdney-9fkv9)**
849
+
**[Coba di CodeSandbox](https://codesandbox.io/s/infallible-dewdney-9fkv9)**
850
850
851
851
Now typing has a lot less stutter -- although we pay for this by showing the results with a lag.
852
852
@@ -876,7 +876,7 @@ function ProfilePage({ resource }) {
876
876
}
877
877
```
878
878
879
-
**[Try it on CodeSandbox](https://codesandbox.io/s/proud-tree-exg5t)**
879
+
**[Coba di CodeSandbox](https://codesandbox.io/s/proud-tree-exg5t)**
880
880
881
881
The API call duration in this example is randomized. If you keep refreshing it, you will notice that sometimes the posts arrive first, and sometimes the "fun facts" arrive first.
882
882
@@ -891,7 +891,7 @@ One way we could fix it is by putting them both in a single boundary:
891
891
</Suspense>
892
892
```
893
893
894
-
**[Try it on CodeSandbox](https://codesandbox.io/s/currying-violet-5jsiy)**
894
+
**[Coba di CodeSandbox](https://codesandbox.io/s/currying-violet-5jsiy)**
895
895
896
896
The problem with this is that now we *always* wait for both of them to be fetched. However, if it's the *posts* that came back first, there's no reason to delay showing them. When fun facts load later, they won't shift the layout because they're already below the posts.
897
897
@@ -921,7 +921,7 @@ function ProfilePage({ resource }) {
921
921
}
922
922
```
923
923
924
-
**[Try it on CodeSandbox](https://codesandbox.io/s/black-wind-byilt)**
924
+
**[Coba di CodeSandbox](https://codesandbox.io/s/black-wind-byilt)**
925
925
926
926
The `revealOrder="forwards"` option means that the closest `<Suspense>` nodes inside this list **will only "reveal" their content in the order they appear in the tree -- even if the data for them arrives in a different order**. `<SuspenseList>` has other interesting modes: try changing `"forwards"` to `"backwards"` or `"together"` and see what happens.
0 commit comments