`.
- Biasanya, Anda akan menggunakan *ref* untuk tindakan non-destruktif seperti fokus, *scrolling*, atau mengukur elemen-elemen DOM.
- Komponen tidak secara *default* mengekspos simpul DOM-nya. Anda dapat memilih untuk mengekspos simpul DOM dengan menggunakan `forwardRef` dan mengoper argumen `ref` kedua ke simpul yang spesifik.
- Hindari mengubah simpul DOM yang dikelola oleh React.
- Jika Anda mengubah simpul DOM yang dikelola oleh React, ubah bagian yang tidak perlu diperbarui oleh React.
+=======
+- Refs are a generic concept, but most often you'll use them to hold DOM elements.
+- You instruct React to put a DOM node into `myRef.current` by passing `
`.
+- Usually, you will use refs for non-destructive actions like focusing, scrolling, or measuring DOM elements.
+- A component doesn't expose its DOM nodes by default. You can opt into exposing a DOM node by using the `ref` prop.
+- Avoid changing DOM nodes managed by React.
+- If you do modify DOM nodes managed by React, modify parts that React has no reason to update.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
@@ -948,7 +988,7 @@ const catList = [];
for (let i = 0; i < 10; i++) {
catList.push({
id: i,
- imageUrl: 'https://placekitten.com/250/200?image=' + i
+ imageUrl: 'https://loremflickr.com/250/200/cat?lock=' + i
});
}
@@ -1065,7 +1105,7 @@ const catList = [];
for (let i = 0; i < 10; i++) {
catList.push({
id: i,
- imageUrl: 'https://placekitten.com/250/200?image=' + i
+ imageUrl: 'https://loremflickr.com/250/200/cat?lock=' + i
});
}
@@ -1117,7 +1157,11 @@ Buat agar saat tombol "Search" diklik, fokus masuk ke dalam input. Perhatikan ba
+<<<<<<< HEAD
Anda akan memerlukan `forwardRef` untuk memungkinkan eksposisi sebuah simpul DOM dari komponen Anda sendiri seperti `SearchInput`.
+=======
+You'll need to pass `ref` as a prop to opt into exposing a DOM node from your own component like `SearchInput`.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
@@ -1202,18 +1246,14 @@ export default function SearchButton({ onClick }) {
```
```js src/SearchInput.js
-import { forwardRef } from 'react';
-
-export default forwardRef(
- function SearchInput(props, ref) {
- return (
-
- );
- }
-);
+export default function SearchInput({ ref }) {
+ return (
+
+ );
+}
```
```css
diff --git a/src/content/learn/passing-data-deeply-with-context.md b/src/content/learn/passing-data-deeply-with-context.md
index f2ac92c8cf..bd3ae67e55 100644
--- a/src/content/learn/passing-data-deeply-with-context.md
+++ b/src/content/learn/passing-data-deeply-with-context.md
@@ -468,15 +468,19 @@ import { LevelContext } from './LevelContext.js';
export default function Section({ level, children }) {
return (
);
}
```
+<<<<<<< HEAD
Ini memberitahu React: "jika ada komponen di dalam `
` ini yang meminta `LevelContext`, berikan `level` ini." Komponen akan menggunakan nilai dari `` terdekat di pohon UI (*tree*) di atasnya.
+=======
+This tells React: "if any component inside this `` asks for `LevelContext`, give them this `level`." The component will use the value of the nearest `` in the UI tree above it.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
@@ -514,9 +518,9 @@ import { LevelContext } from './LevelContext.js';
export default function Section({ level, children }) {
return (
);
}
@@ -566,9 +570,15 @@ export const LevelContext = createContext(1);
Hasilnya sama dengan kode aslinya, tapi Anda tidak perlu mengoper *prop* `level` ke setiap komponen `Heading`! Sebagai gantinya, ia "mencari tahu" *level heading*-nya dengan meminta `Section` terdekat di atasnya:
+<<<<<<< HEAD
1. Anda mengoper *prop* `level` ke ``.
2. `Section` membungkus anaknya dengan ``.
3. `Heading` meminta nilai terdekat dari `LevelContext` di atasnya dengan `useContext(LevelContext)`.
+=======
+1. You pass a `level` prop to the ``.
+2. `Section` wraps its children into ``.
+3. `Heading` asks the closest value of `LevelContext` above with `useContext(LevelContext)`.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
## Menggunakan dan menyediakan *context* dari komponen yang sama {/*using-and-providing-context-from-the-same-component*/}
@@ -595,9 +605,9 @@ export default function Section({ children }) {
const level = useContext(LevelContext);
return (
);
}
@@ -643,9 +653,9 @@ export default function Section({ children }) {
const level = useContext(LevelContext);
return (
);
}
@@ -776,9 +786,9 @@ export default function Section({ children, isFancy }) {
'section ' +
(isFancy ? 'fancy' : '')
}>
-
+
{children}
-
+
);
}
@@ -864,6 +874,7 @@ Pada umumnya, jika beberapa informasi dibutuhkan oleh komponen yang jauh di bebe
+<<<<<<< HEAD
* *Context* memungkinkan komponen menyediakan beberapa informasi ke keseluruhan pohon (*tree*) di bawahnya.
* Untuk mengoper *context*:
1. Buat dan ekspor ia dengan `export const MyContext = createContext(defaultValue)`.
@@ -872,6 +883,16 @@ Pada umumnya, jika beberapa informasi dibutuhkan oleh komponen yang jauh di bebe
* *Context* melewati komponen apa pun di tengahnya.
* *Context* memungkinkan Anda menulis komponen yang "beradaptasi dengan sekitar mereke".
* Sebelum Anda menggunakan *context*, coba oper *props* atau oper JSX sebagai `children`.
+=======
+* Context lets a component provide some information to the entire tree below it.
+* To pass context:
+ 1. Create and export it with `export const MyContext = createContext(defaultValue)`.
+ 2. Pass it to the `useContext(MyContext)` Hook to read it in any child component, no matter how deep.
+ 3. Wrap children into `` to provide it from a parent.
+* Context passes through any components in the middle.
+* Context lets you write components that "adapt to their surroundings".
+* Before you use context, try passing props or passing JSX as `children`.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
@@ -1022,7 +1043,11 @@ li {
Hapus prop `imageSize` dari semua komponen.
+<<<<<<< HEAD
Buat dan ekspor `ImageSizeContext` dari `Context.js`. Lalu bungkus List ke `` untuk mengoper nilai ke bawah, dan `useContext(ImageSizeContext)` untuk membacanya di `PlaceImage`:
+=======
+Create and export `ImageSizeContext` from `Context.js`. Then wrap the List into `` to pass the value down, and `useContext(ImageSizeContext)` to read it in the `PlaceImage`:
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
@@ -1036,7 +1061,7 @@ export default function App() {
const [isLarge, setIsLarge] = useState(false);
const imageSize = isLarge ? 150 : 100;
return (
-
-
+
)
}
diff --git a/src/content/learn/react-compiler.md b/src/content/learn/react-compiler.md
index 19538ef340..b21eb8c000 100644
--- a/src/content/learn/react-compiler.md
+++ b/src/content/learn/react-compiler.md
@@ -3,7 +3,11 @@ title: Kompilator React
---
+<<<<<<< HEAD
Halaman ini akan memberikan pengantar tentang Kompilator React eksperimental baru dan cara menjalankannya dengan sukses.
+=======
+This page will give you an introduction to React Compiler and how to try it out successfully.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
@@ -12,13 +16,20 @@ Dokumentasi ini masih dalam tahap pengembangan. Dokumentasi lebih lanjut tersedi
+<<<<<<< HEAD
* Memulai dengan kompilator
* Menginstal kompilator dan plugin eslint
* Memecahkan masalah
+=======
+* Getting started with the compiler
+* Installing the compiler and ESLint plugin
+* Troubleshooting
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
+<<<<<<< HEAD
Kompilator React adalah kompilator eksperimental baru yang kami jadikan sumber terbuka untuk mendapatkan umpan balik awal dari komunitas. Masih ada beberapa kekurangan dan belum sepenuhnya siap untuk produksi.
Kompilator React membutuhkan React 19 RC. Jika Anda tidak dapat mengupgrade ke React 19, Anda dapat mencoba implementasi *userspace* dari fungsi *cache* seperti yang dijelaskan di [Kelompok Kerja](https://github.com/reactwg/react-compiler/discussions/6).
@@ -27,6 +38,30 @@ Kompilator React membutuhkan React 19 RC. Jika Anda tidak dapat mengupgrade ke R
Kompilator React adalah kompilator eksperimental baru yang kami jadikan sumber terbuka untuk mendapatkan umpan balik awal dari komunitas. Ini adalah alat yang digunakan pada waktu kompilasi yang secara otomatis mengoptimalkan aplikasi React Anda. Alat ini bekerja dengan JavaScript biasa, dan memahami [Aturan React](/reference/rules), sehingga Anda tidak perlu menulis ulang kode apa pun untuk menggunakannya.
Kompilator juga mencakup plugin [eslint](#menginstal-plugin-eslint-kompilator-react) yang menampilkan analisis dari kompilator langsung di editor Anda. Plugin ini berjalan secara independen dari kompilator dan dapat digunakan bahkan jika Anda tidak menggunakan kompilator dalam aplikasi Anda. Kami merekomendasikan semua pengembang React untuk menggunakan plugin eslint ini untuk membantu meningkatkan kualitas kode Anda.
+=======
+React Compiler is a new compiler currently in Beta, that we've open sourced to get early feedback from the community. While it has been used in production at companies like Meta, rolling out the compiler to production for your app will depend on the health of your codebase and how well you’ve followed the [Rules of React](/reference/rules).
+
+The latest Beta release can be found with the `@beta` tag, and daily experimental releases with `@experimental`.
+
+
+React Compiler is a new compiler that we've open sourced to get early feedback from the community. It is a build-time only tool that automatically optimizes your React app. It works with plain JavaScript, and understands the [Rules of React](/reference/rules), so you don't need to rewrite any code to use it.
+
+The compiler also includes an [ESLint plugin](#installing-eslint-plugin-react-compiler) that surfaces the analysis from the compiler right in your editor. **We strongly recommend everyone use the linter today.** The linter does not require that you have the compiler installed, so you can use it even if you are not ready to try out the compiler.
+
+The compiler is currently released as `beta`, and is available to try out on React 17+ apps and libraries. To install the Beta:
+
+
+npm install -D babel-plugin-react-compiler@beta eslint-plugin-react-compiler@beta
+
+
+Or, if you're using Yarn:
+
+
+yarn add -D babel-plugin-react-compiler@beta eslint-plugin-react-compiler@beta
+
+
+If you are not using React 19 yet, please see [the section below](#using-react-compiler-with-react-17-or-18) for further instructions.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
### Apa yang dilakukan oleh kompilator? {/*what-does-the-compiler-do*/}
@@ -34,7 +69,15 @@ Untuk mengoptimalkan aplikasi, Kompilator React secara otomatis melakukan memois
Kompilator menggunakan pengetahuannya tentang JavaScript dan aturan React untuk secara otomatis melakukan memoisasi nilai atau kelompok nilai dalam komponen dan *hook* Anda. Jika ia mendeteksi pelanggaran aturan, ia akan melewati hanya komponen atau *hook* tersebut, dan melanjutkan kompilasi kode lain dengan aman
+<<<<<<< HEAD
Jika basis kode Anda sudah sangat ter-memoisasi dengan baik, Anda mungkin tidak mengharapkan peningkatan kinerja yang signifikan dengan kompilator ini. Namun, dalam praktiknya, memoisasi dependensi yang benar yang menyebabkan masalah kinerja adalah hal yang sulit dilakukan dengan tepat secara manual.
+=======
+
+React Compiler can statically detect when Rules of React are broken, and safely opt-out of optimizing just the affected components or hooks. It is not necessary for the compiler to optimize 100% of your codebase.
+
+
+If your codebase is already very well-memoized, you might not expect to see major performance improvements with the compiler. However, in practice memoizing the correct dependencies that cause performance issues is tricky to get right by hand.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
#### Jenis memoisasi apa yang ditambahkan oleh Kompilator React? {/*what-kind-of-memoization-does-react-compiler-add*/}
@@ -96,6 +139,7 @@ Namun, jika `expensivelyProcessAReallyLargeArrayOfObjects` adalah fungsi yang be
Jadi, jika `expensivelyProcessAReallyLargeArrayOfObjects` digunakan dalam banyak komponen yang berbeda, bahkan jika item yang sama persis dilewatkan, perhitungan mahal tersebut akan dijalankan secara berulang. Kami merekomendasikan untuk [melakukan profil](https://react.dev/reference/react/useMemo#how-to-tell-if-a-calculation-is-expensive) terlebih dahulu untuk melihat apakah benar-benar mahal sebelum membuat kode menjadi lebih rumit.
+<<<<<<< HEAD
### Apa yang diasumsikan oleh kompilator? {/*what-does-the-compiler-assume*/}
React Compiler assumes that your code:
@@ -109,6 +153,11 @@ Kompilator React dapat memverifikasi banyak Aturan React secara statis, dan akan
### Haruskah saya mencoba kompilator? {/*should-i-try-out-the-compiler*/}
Harap dicatat bahwa kompilator ini masih eksperimental dan memiliki beberapa kekurangan. Meskipun telah digunakan di produksi oleh perusahaan seperti Meta, mengimplementasikan kompilator ke produksi untuk aplikasi Anda akan bergantung pada keadaan kode Anda dan sejauh mana Anda mengikuti [Aturan React](/reference/rules).
+=======
+### Should I try out the compiler? {/*should-i-try-out-the-compiler*/}
+
+Please note that the compiler is still in Beta and has many rough edges. While it has been used in production at companies like Meta, rolling out the compiler to production for your app will depend on the health of your codebase and how well you've followed the [Rules of React](/reference/rules).
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
**Anda tidak perlu terburu-buru menggunakan kompilator sekarang. Tidak apa-apa untuk menunggu sampai mencapai rilis stabil sebelum mengadopsinya.** Namun, kami menghargai jika Anda mencobanya dalam eksperimen kecil di aplikasi Anda sehingga Anda dapat [memberikan umpan balik](#reporting-issues) kepada kami untuk membantu membuat kompilator menjadi lebih baik.
@@ -116,6 +165,7 @@ Harap dicatat bahwa kompilator ini masih eksperimental dan memiliki beberapa kek
Selain dokumen ini, kami sarankan untuk memeriksa [Kelompok Kerja Kompilator React](https://github.com/reactwg/react-compiler) untuk informasi tambahan dan diskusi tentang kompilator.
+<<<<<<< HEAD
### Memeriksa kompatibilitas {/*checking-compatibility*/}
Sebelum menginstal kompilator, Anda dapat memeriksa apakah kode Anda kompatibel:
@@ -141,12 +191,38 @@ Found no usage of incompatible libraries.
### Menginstal plugin eslint-plugin-react-compiler {/*installing-eslint-plugin-react-compiler*/}
Kompilator React juga menyediakan plugin eslint. Plugin eslint dapat digunakan **secara independen** dari kompilator, yang berarti Anda dapat menggunakan plugin eslint bahkan jika Anda tidak menggunakan kompilator.
+=======
+### Installing eslint-plugin-react-compiler {/*installing-eslint-plugin-react-compiler*/}
+
+React Compiler also powers an ESLint plugin. The ESLint plugin can be used **independently** of the compiler, meaning you can use the ESLint plugin even if you don't use the compiler.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
-npm install eslint-plugin-react-compiler
+npm install -D eslint-plugin-react-compiler@beta
+<<<<<<< HEAD
Kemudian, tambahkan plugin tersebut ke konfigurasi eslint Anda:
+=======
+Then, add it to your ESLint config:
+
+```js
+import reactCompiler from 'eslint-plugin-react-compiler'
+
+export default [
+ {
+ plugins: {
+ 'react-compiler': reactCompiler,
+ },
+ rules: {
+ 'react-compiler/react-compiler': 'error',
+ },
+ },
+]
+```
+
+Or, in the deprecated eslintrc config format:
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
```js
module.exports = {
@@ -154,14 +230,22 @@ module.exports = {
'eslint-plugin-react-compiler',
],
rules: {
- 'react-compiler/react-compiler': "error",
+ 'react-compiler/react-compiler': 'error',
},
}
```
+<<<<<<< HEAD
Plugin eslint akan menampilkan pelanggaran aturan React di editor Anda. Ketika ini terjadi, artinya kompilator telah melewati optimasi komponen atau hook tersebut. Ini adalah hal yang wajar, dan kompilator dapat melanjutkan dan mengoptimasi kode lain dalam aplikasi Anda.
**Anda tidak perlu memperbaiki semua pelanggaran eslint segera.** Anda dapat menanganinya sesuai keinginan Anda untuk meningkatkan jumlah komponen dan hook yang dioptimalkan, tetapi tidak diperlukan untuk memperbaiki semuanya sebelum Anda dapat menggunakan kompilator.
+=======
+The ESLint plugin will display any violations of the rules of React in your editor. When it does this, it means that the compiler has skipped over optimizing that component or hook. This is perfectly okay, and the compiler can recover and continue optimizing other components in your codebase.
+
+
+**You don't have to fix all ESLint violations straight away.** You can address them at your own pace to increase the amount of components and hooks being optimized, but it is not required to fix everything before you can use the compiler.
+
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
### Mengimplementasikan kompilator ke kode Anda {/*using-the-compiler-effectively*/}
@@ -178,6 +262,7 @@ const ReactCompilerConfig = {
};
```
+<<<<<<< HEAD
Dalam kasus yang jarang terjadi, Anda juga dapat mengonfigurasi kompilator untuk berjalan dalam mode "opt-in" menggunakan opsi `compilationMode: "annotation"`. Ini membuat kompilator hanya mengkompilasi komponen dan hook yang dianotasi dengan direktif `"use memo"`. Harap dicatat bahwa mode `annotation` adalah mode sementara untuk membantu pengguna awal, dan bahwa kami tidak bermaksud agar direktif `"use memo"` digunakan dalam jangka panjang.
```js {2,7}
@@ -193,17 +278,59 @@ export default function App() {
```
Ketika Anda lebih percaya diri dengan mengimplementasikan kompilator, Anda dapat meningkatkan cakupan ke direktori lain dan secara perlahan mengimplementasikannya ke seluruh aplikasi Anda.
+=======
+When you have more confidence with rolling out the compiler, you can expand coverage to other directories as well and slowly roll it out to your whole app.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
#### Proyek baru {/*new-projects*/}
Jika Anda memulai proyek baru, Anda dapat mengaktifkan kompilator pada seluruh kode Anda, yang merupakan perilaku bawaan.
+<<<<<<< HEAD
## Penggunaan {/*installation*/}
+=======
+### Using React Compiler with React 17 or 18 {/*using-react-compiler-with-react-17-or-18*/}
+
+React Compiler works best with React 19 RC. If you are unable to upgrade, you can install the extra `react-compiler-runtime` package which will allow the compiled code to run on versions prior to 19. However, note that the minimum supported version is 17.
+
+
+npm install react-compiler-runtime@beta
+
+
+You should also add the correct `target` to your compiler config, where `target` is the major version of React you are targeting:
+
+```js {3}
+// babel.config.js
+const ReactCompilerConfig = {
+ target: '18' // '17' | '18' | '19'
+};
+
+module.exports = function () {
+ return {
+ plugins: [
+ ['babel-plugin-react-compiler', ReactCompilerConfig],
+ ],
+ };
+};
+```
+
+### Using the compiler on libraries {/*using-the-compiler-on-libraries*/}
+
+React Compiler can also be used to compile libraries. Because React Compiler needs to run on the original source code prior to any code transformations, it is not possible for an application's build pipeline to compile the libraries they use. Hence, our recommendation is for library maintainers to independently compile and test their libraries with the compiler, and ship compiled code to npm.
+
+Because your code is pre-compiled, users of your library will not need to have the compiler enabled in order to benefit from the automatic memoization applied to your library. If your library targets apps not yet on React 19, specify a minimum [`target` and add `react-compiler-runtime` as a direct dependency](#using-react-compiler-with-react-17-or-18). The runtime package will use the correct implementation of APIs depending on the application's version, and polyfill the missing APIs if necessary.
+
+Library code can often require more complex patterns and usage of escape hatches. For this reason, we recommend ensuring that you have sufficient testing in order to identify any issues that might arise from using the compiler on your library. If you identify any issues, you can always opt-out the specific components or hooks with the [`'use no memo'` directive](#something-is-not-working-after-compilation).
+
+Similarly to apps, it is not necessary to fully compile 100% of your components or hooks to see benefits in your library. A good starting point might be to identify the most performance sensitive parts of your library and ensuring that they don't break the [Rules of React](/reference/rules), which you can use `eslint-plugin-react-compiler` to identify.
+
+## Usage {/*installation*/}
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
### Babel {/*usage-with-babel*/}
-npm install babel-plugin-react-compiler
+npm install babel-plugin-react-compiler@beta
Kompilator mencakup *plugin* Babel yang dapat Anda gunakan dalam jalur pembangunan Anda untuk menjalankan kompilator.
@@ -252,6 +379,7 @@ export default defineConfig(() => {
### Next.js {/*usage-with-nextjs*/}
+<<<<<<< HEAD
Next.js memiliki konfigurasi eksperimental untuk mengaktifkan React Compiler. Hal ini secara otomatis memastikan Babel disiapkan dengan `babel-plugin-react-compiler`.
- Instal Next.js *canary*, yang menggunakan *React 19 Release Candidate*
@@ -282,6 +410,9 @@ Menggunakan opsi eksperimental memastikan dukungan untuk Kompilator React di:
- *Webpack* (bawaan)
- *Turbopack* (opsional melalui `--turbo`)
+=======
+Please refer to the [Next.js docs](https://nextjs.org/docs/app/api-reference/next-config-js/reactCompiler) for more information.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
### Remix {/*usage-with-remix*/}
Instal `vite-plugin-babel`, dan tambahkan *plugin* Babel kompilator ke dalamnya:
@@ -314,6 +445,7 @@ export default defineConfig({
### Webpack {/*usage-with-webpack*/}
+<<<<<<< HEAD
Anda dapat membuat *loader* Anda sendiri untuk React Compiler, seperti berikut:
```js
@@ -352,6 +484,13 @@ module.exports = reactCompilerLoader;
### Expo {/*usage-with-expo*/}
Silahkan merujuk ke [Dokumen Expo](https://docs.expo.dev/preview/react-compiler/) untuk mengaktifkan dan menggunakan Kompilator React di aplikasi Expo.
+=======
+A community webpack loader is [now available here](https://github.com/SukkaW/react-compiler-webpack).
+
+### Expo {/*usage-with-expo*/}
+
+Please refer to [Expo's docs](https://docs.expo.dev/guides/react-compiler/) to enable and use the React Compiler in Expo apps.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
### Metro (React Native) {/*usage-with-react-native-metro*/}
@@ -371,22 +510,45 @@ Untuk melaporkan masalah, harap pertama-tama buat contoh minimal di [*React Comp
Anda juga dapat memberikan umpan balik di Kelompok Kerja React Compiler dengan melamar menjadi anggota. Silakan lihat [README untuk detail lebih lanjut tentang bergabung](https://github.com/reactwg/react-compiler).
+<<<<<<< HEAD
### Eror `(0 , _c) is not a function` {/*0--_c-is-not-a-function-error*/}
Ini terjadi jika Anda tidak menggunakan React 19 RC atau versi yang lebih baru. Untuk memperbaikinya, [tingkatkan aplikasi Anda ke React 19 RC terlebih dahulu](https://react.dev/blog/2024/04/25/react-19-upgrade-guide).
Jika Anda tidak dapat meningkatkan ke React 19, Anda dapat mencoba implementasi fungsi cache dari ruang pengguna seperti yang dijelaskan dalam [Kelompok Kerja](https://github.com/reactwg/react-compiler/discussions/6). Namun, harap dicatat bahwa ini tidak dianjurkan dan Anda harus memperbarui ke React 19 jika memungkinkan.
+=======
+### What does the compiler assume? {/*what-does-the-compiler-assume*/}
+
+React Compiler assumes that your code:
+
+1. Is valid, semantic JavaScript.
+2. Tests that nullable/optional values and properties are defined before accessing them (for example, by enabling [`strictNullChecks`](https://www.typescriptlang.org/tsconfig/#strictNullChecks) if using TypeScript), i.e., `if (object.nullableProperty) { object.nullableProperty.foo }` or with optional-chaining `object.nullableProperty?.foo`.
+3. Follows the [Rules of React](https://react.dev/reference/rules).
+
+React Compiler can verify many of the Rules of React statically, and will safely skip compilation when it detects an error. To see the errors we recommend also installing [eslint-plugin-react-compiler](https://www.npmjs.com/package/eslint-plugin-react-compiler).
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
### Bagaimana cara saya mengetahui komponen saya telah dioptimalkan? {/*how-do-i-know-my-components-have-been-optimized*/}
+<<<<<<< HEAD
[React Devtools](/learn/react-developer-tools) (v5.0+) memiliki dukungan bawaan untuk React Compiler dan akan menampilkan lencana "Memo ✨" di samping komponen yang telah dioptimalkan oleh kompilator.
### Sesuatu tidak berfungsi setelah kompilasi {/*something-is-not-working-after-compilation*/}
Jika Anda memiliki eslint-plugin-react-compiler terinstal, kompilator akan menampilkan pelanggaran aturan React di editor Anda. Ketika ini terjadi, itu berarti kompilator telah melewati optimasi komponen atau *hook* tersebut. Ini sepenuhnya normal, dan kompilator dapat melanjutkan untuk mengoptimalkan komponen lain di basis kode Anda. **Anda tidak perlu memperbaiki semua pelanggaran eslint segera**. Anda dapat menanganinya sesuai kecepatan Anda sendiri untuk meningkatkan jumlah komponen dan *hook* yang dioptimalkan.
+=======
+[React DevTools](/learn/react-developer-tools) (v5.0+) and [React Native DevTools](https://reactnative.dev/docs/react-native-devtools) have built-in support for React Compiler and will display a "Memo ✨" badge next to components that have been optimized by the compiler.
+
+### Something is not working after compilation {/*something-is-not-working-after-compilation*/}
+If you have eslint-plugin-react-compiler installed, the compiler will display any violations of the rules of React in your editor. When it does this, it means that the compiler has skipped over optimizing that component or hook. This is perfectly okay, and the compiler can recover and continue optimizing other components in your codebase. **You don't have to fix all ESLint violations straight away.** You can address them at your own pace to increase the amount of components and hooks being optimized.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
Namun, karena sifat fleksibel dan dinamis dari JavaScript, tidak mungkin untuk mendeteksi semua kasus secara komprehensif. *Bug* dan perilaku tidak terdefinisi seperti *loop* tak hingga mungkin terjadi dalam kasus-kasus tersebut.
+<<<<<<< HEAD
Jika aplikasi Anda tidak berfungsi dengan baik setelah kompilasi dan Anda tidak melihat eror eslint, kompilator mungkin salah mengompilasi kode Anda. Untuk memastikan hal ini, coba untuk menghilangkan masalah dengan secara agresif memilih keluar komponen atau hook yang Anda pikir mungkin terkait melalui [direktif `"use no memo"`](#opt-out-of-the-compiler-for-a-component).
+=======
+If your app doesn't work properly after compilation and you aren't seeing any ESLint errors, the compiler may be incorrectly compiling your code. To confirm this, try to make the issue go away by aggressively opting out any component or hook you think might be related via the [`"use no memo"` directive](#opt-out-of-the-compiler-for-a-component).
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
```js {2}
function SuspiciousComponent() {
diff --git a/src/content/learn/react-developer-tools.md b/src/content/learn/react-developer-tools.md
index f37009eeb8..8d49dd4db6 100644
--- a/src/content/learn/react-developer-tools.md
+++ b/src/content/learn/react-developer-tools.md
@@ -56,17 +56,21 @@ Reload website Anda sekarang untuk melihatnya di React Developer Tools.

## Mobile (React Native) {/*mobile-react-native*/}
+<<<<<<< HEAD
React Developer Tools dapat digunakan untuk memeriksa aplikasi yang dibangun dengan [React Native](https://reactnative.dev/) juga.
Cara termudah untuk menggunakan React Developer Tools adalah dengan menginstalnya secara global:
```bash
# Yarn
yarn global add react-devtools
+=======
-# Npm
-npm install -g react-devtools
-```
+To inspect apps built with [React Native](https://reactnative.dev/), you can use [React Native DevTools](https://reactnative.dev/docs/react-native-devtools), the built-in debugger that deeply integrates React Developer Tools. All features work identically to the browser extension, including native element highlighting and selection.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
+
+[Learn more about debugging in React Native.](https://reactnative.dev/docs/debugging)
+<<<<<<< HEAD
Selanjutnya buka React Developer Tools dari terminal:
```bash
react-devtools
@@ -78,3 +82,6 @@ React Developer Tools akan terhubung ke aplikasi React Native lokal yang sedang
[Pelajari lebih lanjut tentang debugging React Native.](https://reactnative.dev/docs/debugging)
+=======
+> For versions of React Native earlier than 0.76, please use the standalone build of React DevTools by following the [Safari and other browsers](#safari-and-other-browsers) guide above.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
diff --git a/src/content/learn/render-and-commit.md b/src/content/learn/render-and-commit.md
index a66b666e53..a7400f09b7 100644
--- a/src/content/learn/render-and-commit.md
+++ b/src/content/learn/render-and-commit.md
@@ -70,9 +70,15 @@ Cobalah memberi komentar di luar dari `root.render()` dan lihat komponen tersebu
Setelah komponen telah pertama kali di*render*, Anda dapat memicu *render* kembali dengan memperbarui *state* menggunakan [fungsi `set`.](/reference/react/useState#setstate) Mengubah *state* komponen Anda otomatis akan membuat antrian proses *render*. (Anda dapat membayangkan ada sebuah restoran dimana pengunjung memesan teh, hidangan penutup, dan semua hal tersebut dipesan setelah melakukan pesanan pertama, tergantung pada keadaan haus atau lapar dari pengunjung)
+<<<<<<< HEAD
+=======
+
+
+
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
## Langkah 2: React me-render komponen Anda {/*step-2-react-renders-your-components*/}
@@ -84,7 +90,11 @@ Setelah Anda memicu sebuah *render*, React memanggil komponen Anda untuk menemuk
Proses ini bersifat rekursif: jika komponen yang diperbarui mengembalikan beberapa komponen lain, React akan me-*render* komponen _itu_ berikutnya, dan jika komponen itu juga mengembalikan sesuatum React akan me-*render* komponen _itu_ berikutnya, dan seterusnya. Proses tersebut akan berlanjut sampai tidak terdapat komponen bersarang dan React mengetahui persis apa yang harus ditampilkan pada layar.
+<<<<<<< HEAD
Dalam contoh berikut, React akan memanggil `Gallery()` dan `Image()` beberapa kali:
+=======
+In the following example, React will call `Gallery()` and `Image()` several times:
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
@@ -148,10 +158,17 @@ Perilaku bawaan dari proses *render* semua komponen bersarang di dalam komponen
## Langkah 3: React mengirimkan perubahan kepada DOM {/*step-3-react-commits-changes-to-the-dom*/}
+<<<<<<< HEAD
Setelah proses _render_ (memanggil) komponen Anda, React akan memodifikasi DOM.
* **Untuk _render_ awal,** React akan menggunakan [`appendChild()`](https://developer.mozilla.org/docs/Web/API/Node/appendChild) DOM API untuk meletakkan semua simpul DOM yang telah dibuat ke dalam layar.
* **Untuk _render_ ulang,** React akan menerapkan operasi minimal yang diperlukan (dihitung saat proses *render*!) untuk membuat DOM sama dengan keluaran *render* terakhir.
+=======
+After rendering (calling) your components, React will modify the DOM.
+
+* **For the initial render,** React will use the [`appendChild()`](https://developer.mozilla.org/docs/Web/API/Node/appendChild) DOM API to put all the DOM nodes it has created on screen.
+* **For re-renders,** React will apply the minimal necessary operations (calculated while rendering!) to make the DOM match the latest rendering output.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
**React hanya mengubah simpul DOM jika ada perbedaan diantara proses _render_.** Sebagai contoh, berikut terdapat komponen yang me-*render* ulang dengan properti berbeda yang dikirimkan setiap detik. Perhatikan bagaimana Anda dapat menambahkan beberapa teks ke dalam ``, memperbarui nilai ``, tetapi teks tersebut tidak menghilang saat komponen me-*render* ulang:
diff --git a/src/content/learn/setup.md b/src/content/learn/setup.md
new file mode 100644
index 0000000000..2c46ee1485
--- /dev/null
+++ b/src/content/learn/setup.md
@@ -0,0 +1,28 @@
+---
+title: Setup
+---
+
+
+React integrates with tools like editors, TypeScript, browser extensions, and compilers. This section will help you get your environment set up.
+
+
+
+## Editor Setup {/*editor-setup*/}
+
+See our [recommended editors](/learn/editor-setup) and learn how to set them up to work with React.
+
+## Using TypeScript {/*using-typescript*/}
+
+TypeScript is a popular way to add type definitions to JavaScript codebases. [Learn how to integrate TypeScript into your React projects](/learn/typescript).
+
+## React Developer Tools {/*react-developer-tools*/}
+
+React Developer Tools is a browser extension that can inspect React components, edit props and state, and identify performance problems. Learn how to install it [here](learn/react-developer-tools).
+
+## React Compiler {/*react-compiler*/}
+
+React Compiler is a tool that automatically optimizes your React app. [Learn more](/learn/react-compiler).
+
+## Next steps {/*next-steps*/}
+
+Head to the [Quick Start](/learn) guide for a tour of the most important React concepts you will encounter every day.
diff --git a/src/content/learn/state-a-components-memory.md b/src/content/learn/state-a-components-memory.md
index bd9331cc2f..768f6be43c 100644
--- a/src/content/learn/state-a-components-memory.md
+++ b/src/content/learn/state-a-components-memory.md
@@ -1455,7 +1455,11 @@ Jika *linter* Anda [disetel untuk React](/learn/editor-setup#linting), Anda seha
#### Menghapus state yang tidak perlu {/*remove-unnecessary-state*/}
+<<<<<<< HEAD
Saat tombol ditekan, pada contoh di bawah, sebuah kotak dialog akan muncul untuk diisi pengguna dan akan menambilkan pesan untuk menyapa mereka. Anda sudah coba menggunakan *state* untuk namanya, namun karena suatu hal dia tetap menampilkan "Halo, !"
+=======
+When the button is clicked, this example should ask for the user's name and then display an alert greeting them. You tried to use state to keep the name, but for some reason the first time it shows "Hello, !", and then "Hello, [name]!" with the previous input every time after.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
Untuk memperbaiki kode di bawah, hilangkan variabel *state* yang tidak perlu. (Kita akan bahas [mengapa hal tersebut tidak bekerja](/learn/state-as-a-snapshot) nanti.)
diff --git a/src/content/learn/synchronizing-with-effects.md b/src/content/learn/synchronizing-with-effects.md
index 7e0e6ebc49..f3cd9559ed 100644
--- a/src/content/learn/synchronizing-with-effects.md
+++ b/src/content/learn/synchronizing-with-effects.md
@@ -629,7 +629,11 @@ Lihat contoh di bawah ini untuk cara menangani pola umum.
### Mengontrol *widget* di luar React {/*controlling-non-react-widgets*/}
+<<<<<<< HEAD
Terkadang Anda perlu menambahkan *widget* UI yang tidak ditulis untuk React. Sebagai contoh, katakanlah Anda menambahkan komponen peta ke halaman Anda. Komponen ini memiliki metode `setZoomLevel()`, dan Anda ingin menjaga tingkat *zoom* tetap sinkron dengan variabel *state* `zoomLevel` dalam kode React Anda. *Effect* Anda akan terlihat seperti ini:
+=======
+Sometimes you need to add UI widgets that aren't written in React. For example, let's say you're adding a map component to your page. It has a `setZoomLevel()` method, and you'd like to keep the zoom level in sync with a `zoomLevel` state variable in your React code. Your Effect would look similar to this:
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
```js
useEffect(() => {
diff --git a/src/content/learn/thinking-in-react.md b/src/content/learn/thinking-in-react.md
index caa3d19155..f94ae1789b 100644
--- a/src/content/learn/thinking-in-react.md
+++ b/src/content/learn/thinking-in-react.md
@@ -265,11 +265,19 @@ Pada langkah sebelumnya, Anda menemukan dua bagian status dalam aplikasi ini: te
Sekarang mari kita bahas strateginya:
+<<<<<<< HEAD
1. **Identifikasi komponen yang menggunakan state:**
* `ProductTable` perlu memfilter daftar produk berdasarkan status tersebut (teks pencarian dan nilai kotak centang).
* `SearchBar` perlu menampilkan status tersebut (teks pencarian dan nilai kotak centang).
1. **Temukan induk yang sama:** Komponen induk pertama yang dimiliki oleh kedua komponen tersebut adalah `FilterableProductTable`.
2. **Tentukan di mana state berada**: Kita akan menyimpan teks filter dan nilai state kotak centang di `FilterableProductTable`.
+=======
+1. **Identify components that use state:**
+ * `ProductTable` needs to filter the product list based on that state (search text and checkbox value).
+ * `SearchBar` needs to display that state (search text and checkbox value).
+2. **Find their common parent:** The first parent component both components share is `FilterableProductTable`.
+3. **Decide where the state lives**: We'll keep the filter text and checked state values in `FilterableProductTable`.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
Jadi nilai state akan berada di dalam `FilterableProductTable`.
diff --git a/src/content/learn/tutorial-tic-tac-toe.md b/src/content/learn/tutorial-tic-tac-toe.md
index 5496ee37c1..f4104d6964 100644
--- a/src/content/learn/tutorial-tic-tac-toe.md
+++ b/src/content/learn/tutorial-tic-tac-toe.md
@@ -295,7 +295,11 @@ export default function Square() {
}
```
+<<<<<<< HEAD
Bagian _browser_ seharusnya menampilkan sebuah kotak dengan tanda X di dalamnya seperti ini:
+=======
+The _browser_ section should be displaying a square with an X in it like this:
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d

@@ -1133,7 +1137,11 @@ Memanggil fungsi `setSquares` akan membuat React mengetahui bahwa state dari kom
+<<<<<<< HEAD
JavaScript mendukung [closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) yang berarti fungsi dalam (misalnya `handleClick`) memiliki akses ke variabel dan fungsi yang didefinisikan di fungsi luar (misalnya `Board`). Fungsi `handleClick` dapat membaca state `squares` dan memanggil metode `setSquares` karena keduanya didefinisikan di dalam fungsi `Board`.
+=======
+JavaScript supports [closures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) which means an inner function (e.g. `handleClick`) has access to variables and functions defined in an outer function (e.g. `Board`). The `handleClick` function can read the `squares` state and call the `setSquares` method because they are both defined inside of the `Board` function.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
@@ -1325,7 +1333,11 @@ Mari kita rekap apa yang terjadi ketika pengguna mengeklik kotak kiri atas pada
1. `handleClick` menggunakan argumen (`0`) untuk meng-update elemen pertama dari array `squares` dari `null` menjadi `X`.
1. State `squares` dari komponen `Board` telah diperbarui, sehingga `Board` dan semua anak komponennya di-render ulang. Hal ini menyebabkan prop `value` dari komponen `Square` dengan indeks `0` berubah dari `null` menjadi `X`.
+<<<<<<< HEAD
Pada akhirnya pengguna akan melihat bahwa kotak kiri atas telah berubah dari kosong menjadi bertanda `X` setelah mengekliknya.
+=======
+In the end the user sees that the upper left square has changed from empty to having an `X` after clicking it.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
@@ -1406,7 +1418,11 @@ Tapi tunggu, ada masalah. Coba klik kotak yang sama beberapa kali:
Tanda `X` ditimpa oleh tanda `O`! Meskipun hal ini akan menambah sentuhan yang sangat menarik pada gim ini, kami akan tetap berpegang pada aturan asli untuk saat ini.
+<<<<<<< HEAD
Ketika Anda menandai kotak dengan `X` atau `O`, Anda tidak memeriksa terlebih dahulu apakah kotak tersebut telah memiliki nilai `X` atau `O`. Anda dapat memperbaikinya dengan *return lebih awal*. Anda akan memeriksa apakah kotak tersebut sudah memiliki nilai `X` atau `O`. Jika kotak sudah terisi, Anda akan `return` dalam fungsi `handleClick` lebih awal--sebelum fungsi ini mencoba untuk meng-update state papan.
+=======
+When you mark a square with an `X` or an `O` you aren't first checking to see if the square already has an `X` or `O` value. You can fix this by *returning early*. You'll check to see if the square already has an `X` or an `O`. If the square is already filled, you will `return` in the `handleClick` function early--before it tries to update the board state.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
```js {2,3,4}
function handleClick(i) {
@@ -1556,7 +1572,11 @@ Tidak masalah apakah Anda mendefinisikan `calculateWinner` sebelum atau sesudah
+<<<<<<< HEAD
Anda akan memanggil `calculateWinner(squares)` dalam fungsi `handleClick` komponen `Board` untuk memeriksa apakah pemain telah menang. Anda dapat melakukan pengecekan ini bersamaan dengan pengecekan apakah pengguna telah mengklik kotak yang telah memiliki tanda `X` atau `O`. Kita ingin kembali lebih awal dalam kedua kasus tersebut:
+=======
+You will call `calculateWinner(squares)` in the `Board` component's `handleClick` function to check if a player has won. You can perform this check at the same time you check if a user has clicked a square that already has an `X` or an `O`. We'd like to return early in both cases:
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
```js {2}
function handleClick(i) {
diff --git a/src/content/learn/updating-objects-in-state.md b/src/content/learn/updating-objects-in-state.md
index ead94cc14b..347495e876 100644
--- a/src/content/learn/updating-objects-in-state.md
+++ b/src/content/learn/updating-objects-in-state.md
@@ -58,6 +58,7 @@ Berikut adalah contoh kode yang menampung objek di dalam *state* untuk mereprese
```js
import { useState } from 'react';
+
export default function MovingDot() {
const [position, setPosition] = useState({
x: 0,
@@ -127,6 +128,7 @@ Perhatikan bahwa sekarang titik merah sudah mengikuti kursor Anda ketika Anda me
```js
import { useState } from 'react';
+
export default function MovingDot() {
const [position, setPosition] = useState({
x: 0,
@@ -377,7 +379,11 @@ Perhatikan bahwa `...` sintaksis *spread* sebenarnya adalah "dangkal"--benda-ben
#### Menggunakan satu event handler untuk beberapa bidang {/*using-a-single-event-handler-for-multiple-fields*/}
+<<<<<<< HEAD
Anda juga bisa menggunakan tanda `[` dan `]` di dalam definisi objek untuk menentukan sebuah properti dengan nama yang dinamis. Berikut adalah contoh yang sama, tetapi dengan satu *event handler* daripada tiga yang berbeda:
+=======
+You can also use the `[` and `]` braces inside your object definition to specify a property with a dynamic name. Here is the same example, but with a single event handler instead of three different ones:
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
diff --git a/src/content/learn/you-might-not-need-an-effect.md b/src/content/learn/you-might-not-need-an-effect.md
index 5342a27eda..37f10c338f 100644
--- a/src/content/learn/you-might-not-need-an-effect.md
+++ b/src/content/learn/you-might-not-need-an-effect.md
@@ -408,9 +408,15 @@ function Game() {
Ada dua masalah dengan kode ini.
+<<<<<<< HEAD
Salah satu masalahnya adalah hal ini sangat tidak efisien: komponen (dan turunannya) harus di-*render* ulang di antara setiap panggilan `set` dalam rantai. Dalam contoh di atas, dalam kasus terburuk (`setCard` → *render* → `setGoldCardCount` → *render* → `setRound` → *render* → `setIsGameOver` → *render*) ada tiga *rendering* ulang yang tidak diperlukan pada pohon di bawah ini.
Meskipun tidak lambat, seiring berkembangnya kode Anda, Anda akan menghadapi kasus di mana "rantai" yang Anda tulis tidak sesuai dengan persyaratan baru. Bayangkan Anda menambahkan cara untuk menelusuri sejarah gerakan permainan. Anda akan melakukannya dengan memperbarui setiap variabel *state* ke nilai dari masa lalu. Namun, menyetel *state* `card` ke nilai dari masa lalu akan memicu rantai *Effect* lagi dan mengubah data yang Anda tampilkan. Kode seperti ini seringkali kaku dan rapuh.
+=======
+The first problem is that it is very inefficient: the component (and its children) have to re-render between each `set` call in the chain. In the example above, in the worst case (`setCard` → render → `setGoldCardCount` → render → `setRound` → render → `setIsGameOver` → render) there are three unnecessary re-renders of the tree below.
+
+The second problem is that even if it weren't slow, as your code evolves, you will run into cases where the "chain" you wrote doesn't fit the new requirements. Imagine you are adding a way to step through the history of the game moves. You'd do it by updating each state variable to a value from the past. However, setting the `card` state to a value from the past would trigger the Effect chain again and change the data you're showing. Such code is often rigid and fragile.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
Dalam hal ini, lebih baik menghitung apa yang Anda bisa selama *rendering*, dan sesuaikan *state* di *event handler*:
diff --git a/src/content/reference/react-dom/client/createRoot.md b/src/content/reference/react-dom/client/createRoot.md
index 5c50be07e1..eda42b1f94 100644
--- a/src/content/reference/react-dom/client/createRoot.md
+++ b/src/content/reference/react-dom/client/createRoot.md
@@ -49,7 +49,14 @@ Aplikasi yang sepenuhnya dibuat dengan React biasanya cukup memanggil `createRoo
* **opsional** `onRecoverableError`: *Callback* yang dipanggil saat React berhasil pulih secara otomatis dari kesalahan. Dipanggil dengan `error` yang dikembalikan React, dan obyek `errorInfo` berisi `componentStack`. Beberapa kesalahan yang dapat dipulihkan mungkin akan berisi kesalahan aslinya sebagai `error.cause`.
* **opsional** `identifierPrefix`: Awalan string yang digunakan React untuk ID yang dihasilkan oleh [`useId`.](/reference/react/useId) Berguna untuk mencegah konflik saat menggunakan banyak akar pada halaman yang sama.
+<<<<<<< HEAD
#### Kembalian {/*returns*/}
+=======
+ * **optional** `onCaughtError`: Callback called when React catches an error in an Error Boundary. Called with the `error` caught by the Error Boundary, and an `errorInfo` object containing the `componentStack`.
+ * **optional** `onUncaughtError`: Callback called when an error is thrown and not caught by an Error Boundary. Called with the `error` that was thrown, and an `errorInfo` object containing the `componentStack`.
+ * **optional** `onRecoverableError`: Callback called when React automatically recovers from errors. Called with an `error` React throws, and an `errorInfo` object containing the `componentStack`. Some recoverable errors may include the original error cause as `error.cause`.
+ * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
`createRoot` mengembalikan sebuah objek dengan dua *method*: [`render`](#root-render) dan [`unmount`.](#root-unmount)
@@ -142,7 +149,7 @@ Biasanya, Anda cukup menjalankan kode ini sekali saja pada *startup*. Kode ini a
-```html index.html
+```html public/index.html
My app
@@ -342,10 +349,15 @@ export default function App({counter}) {
Pemanggilan `render` berulang kali biasanya tidak wajar. Pada umumnya komponen Anda akan [memperbarui *state*](/reference/react/useState).
+<<<<<<< HEAD
### Menampilkan dialog untuk *error* yang tidak ditangkap {/*show-a-dialog-for-uncaught-errors*/}
+=======
+### Error logging in production {/*error-logging-in-production*/}
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
-
+By default, React will log all errors to the console. To implement your own error reporting, you can provide the optional error handler root options `onUncaughtError`, `onCaughtError` and `onRecoverableError`:
+<<<<<<< HEAD
`onCaughtError` hanya tersedia di rilis Canary React terbaru.
@@ -788,92 +800,28 @@ import { createRoot } from "react-dom/client";
import App from "./App.js";
import {reportCaughtError} from "./reportError";
import "./styles.css";
+=======
+```js [[1, 6, "onCaughtError"], [2, 6, "error", 1], [3, 6, "errorInfo"], [4, 10, "componentStack", 15]]
+import { createRoot } from "react-dom/client";
+import { reportCaughtError } from "./reportError";
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
const container = document.getElementById("root");
const root = createRoot(container, {
onCaughtError: (error, errorInfo) => {
- if (error.message !== 'Known error') {
+ if (error.message !== "Known error") {
reportCaughtError({
- error,
+ error,
componentStack: errorInfo.componentStack,
});
}
- }
-});
-root.render();
-```
-
-```js src/App.js
-import { useState } from 'react';
-import { ErrorBoundary } from "react-error-boundary";
-
-export default function App() {
- const [error, setError] = useState(null);
-
- function handleUnknown() {
- setError("unknown");
- }
-
- function handleKnown() {
- setError("known");
- }
-
- return (
- <>
- {
- setError(null);
- }}
- >
- {error != null && }
- This error will not show the error dialog:
-
- This error will show the error dialog:
-
-
-
- >
- );
-}
-
-function fallbackRender({ resetErrorBoundary }) {
- return (
-
-
Error Boundary
-
Something went wrong.
-
-
- );
-}
-
-function Throw({error}) {
- if (error === "known") {
- throw new Error('Known error')
- } else {
- foo.bar = 'baz';
- }
-}
-```
-
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "^5.0.0",
- "react-error-boundary": "4.0.3"
},
- "main": "/index.js"
-}
+});
```
-
+The onCaughtError option is a function called with two arguments:
+<<<<<<< HEAD
### Menampilkan dialog untuk *error* yang dapat dipulihkan {/*displaying-a-dialog-for-recoverable-errors*/}
React dapat secara otomatis me-*render* komponen untuk kedua kalinya guna mencoba memulihkan dari *error* yang terjadi saat me-*render*. Jika berhasil, React akan me-log *error* yang dapat dipulihkan ke konsol untuk memberi tahu pengembang aplikasi. Untuk mengatasi perilaku ini, Anda dapat memberikan opsi *root* `onRecoverableError` opsional:
@@ -903,238 +851,113 @@ Pengaturan onRecoverableError adalah fungsi yang d
2. Obyek errorInfo yang mengandung componentStack dari *error* tersebut.
Anda dapat menggunakan opsi *root* `onRecoverableError` untuk menampilkan dialog *error*:
+=======
+1. The error that was thrown.
+2. An errorInfo object that contains the componentStack of the error.
-
-
-```html index.html hidden
-
-
-
- My app
-
-
-
-
-
-
-
-
-
-
-
-
This error occurred at:
-
-
Call stack:
-
-
-
-
This error is not dismissible.
-
-
-
-
-
-```
-
-```css src/styles.css active
-label, button { display: block; margin-bottom: 20px; }
-html, body { min-height: 300px; }
-
-#error-dialog {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- background-color: white;
- padding: 15px;
- opacity: 0.9;
- text-wrap: wrap;
- overflow: scroll;
-}
-
-.text-red {
- color: red;
-}
-
-.-mb-20 {
- margin-bottom: -20px;
-}
-
-.mb-0 {
- margin-bottom: 0;
-}
-
-.mb-10 {
- margin-bottom: 10px;
-}
-
-pre {
- text-wrap: wrap;
-}
+Together with `onUncaughtError` and `onRecoverableError`, you can can implement your own error reporting system:
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
-pre.nowrap {
- text-wrap: nowrap;
-}
+
-.hidden {
- display: none;
+```js src/reportError.js
+function reportError({ type, error, errorInfo }) {
+ // The specific implementation is up to you.
+ // `console.error()` is only used for demonstration purposes.
+ console.error(type, error, "Component Stack: ");
+ console.error("Component Stack: ", errorInfo.componentStack);
}
-```
-
-```js src/reportError.js hidden
-function reportError({ title, error, componentStack, dismissable }) {
- const errorDialog = document.getElementById("error-dialog");
- const errorTitle = document.getElementById("error-title");
- const errorMessage = document.getElementById("error-message");
- const errorBody = document.getElementById("error-body");
- const errorComponentStack = document.getElementById("error-component-stack");
- const errorStack = document.getElementById("error-stack");
- const errorClose = document.getElementById("error-close");
- const errorCause = document.getElementById("error-cause");
- const errorCauseMessage = document.getElementById("error-cause-message");
- const errorCauseStack = document.getElementById("error-cause-stack");
- const errorNotDismissible = document.getElementById("error-not-dismissible");
-
- // Set the title
- errorTitle.innerText = title;
-
- // Display error message and body
- const [heading, body] = error.message.split(/\n(.*)/s);
- errorMessage.innerText = heading;
- if (body) {
- errorBody.innerText = body;
- } else {
- errorBody.innerText = '';
- }
-
- // Display component stack
- errorComponentStack.innerText = componentStack;
- // Display the call stack
- // Since we already displayed the message, strip it, and the first Error: line.
- errorStack.innerText = error.stack.replace(error.message, '').split(/\n(.*)/s)[1];
-
- // Display the cause, if available
- if (error.cause) {
- errorCauseMessage.innerText = error.cause.message;
- errorCauseStack.innerText = error.cause.stack;
- errorCause.classList.remove('hidden');
- } else {
- errorCause.classList.add('hidden');
- }
- // Display the close button, if dismissible
- if (dismissable) {
- errorNotDismissible.classList.add('hidden');
- errorClose.classList.remove("hidden");
- } else {
- errorNotDismissible.classList.remove('hidden');
- errorClose.classList.add("hidden");
+export function onCaughtErrorProd(error, errorInfo) {
+ if (error.message !== "Known error") {
+ reportError({ type: "Caught", error, errorInfo });
}
-
- // Show the dialog
- errorDialog.classList.remove("hidden");
}
-export function reportCaughtError({error, cause, componentStack}) {
- reportError({ title: "Caught Error", error, componentStack, dismissable: true});
-}
-
-export function reportUncaughtError({error, cause, componentStack}) {
- reportError({ title: "Uncaught Error", error, componentStack, dismissable: false });
+export function onUncaughtErrorProd(error, errorInfo) {
+ reportError({ type: "Uncaught", error, errorInfo });
}
-export function reportRecoverableError({error, cause, componentStack}) {
- reportError({ title: "Recoverable Error", error, componentStack, dismissable: true });
+export function onRecoverableErrorProd(error, errorInfo) {
+ reportError({ type: "Recoverable", error, errorInfo });
}
```
```js src/index.js active
import { createRoot } from "react-dom/client";
import App from "./App.js";
-import {reportRecoverableError} from "./reportError";
-import "./styles.css";
+import {
+ onCaughtErrorProd,
+ onRecoverableErrorProd,
+ onUncaughtErrorProd,
+} from "./reportError";
const container = document.getElementById("root");
const root = createRoot(container, {
- onRecoverableError: (error, errorInfo) => {
- reportRecoverableError({
- error,
- cause: error.cause,
- componentStack: errorInfo.componentStack,
- });
- }
+ // Keep in mind to remove these options in development to leverage
+ // React's default handlers or implement your own overlay for development.
+ // The handlers are only specfied unconditionally here for demonstration purposes.
+ onCaughtError: onCaughtErrorProd,
+ onRecoverableError: onRecoverableErrorProd,
+ onUncaughtError: onUncaughtErrorProd,
});
root.render();
```
```js src/App.js
-import { useState } from 'react';
-import { ErrorBoundary } from "react-error-boundary";
+import { Component, useState } from "react";
-// 🚩 Bug: Never do this. This will force an error.
-let errorThrown = false;
-export default function App() {
- return (
- <>
-
- {!errorThrown && }
- This component threw an error, but recovered during a second render.
- Since it recovered, no Error Boundary was shown, but onRecoverableError was used to show an error dialog.
-
-
- >
- );
+function Boom() {
+ foo.bar = "baz";
}
-function fallbackRender() {
- return (
-
-
Error Boundary
-
Something went wrong.
-
- );
-}
+class ErrorBoundary extends Component {
+ state = { hasError: false };
+
+ static getDerivedStateFromError(error) {
+ return { hasError: true };
+ }
-function Throw({error}) {
- // Simulate an external value changing during concurrent render.
- errorThrown = true;
- foo.bar = 'baz';
+ render() {
+ if (this.state.hasError) {
+ return Something went wrong.
;
+ }
+ return this.props.children;
+ }
}
-```
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "^5.0.0",
- "react-error-boundary": "4.0.3"
- },
- "main": "/index.js"
+export default function App() {
+ const [triggerUncaughtError, settriggerUncaughtError] = useState(false);
+ const [triggerCaughtError, setTriggerCaughtError] = useState(false);
+
+ return (
+ <>
+
+ {triggerUncaughtError && }
+
+ {triggerCaughtError && (
+
+
+
+ )}
+ >
+ );
}
```
+<<<<<<< HEAD
---
## Pemecahan masalah {/*troubleshooting*/}
+=======
+## Troubleshooting {/*troubleshooting*/}
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
### Saya telah membuat sebuah akar, namun tidak ada yang tampil {/*ive-created-a-root-but-nothing-is-displayed*/}
diff --git a/src/content/reference/react-dom/client/hydrateRoot.md b/src/content/reference/react-dom/client/hydrateRoot.md
index d406304dc4..82539fd422 100644
--- a/src/content/reference/react-dom/client/hydrateRoot.md
+++ b/src/content/reference/react-dom/client/hydrateRoot.md
@@ -39,11 +39,18 @@ React akan ditambahkan ke dalam HTML yang ada di dalam `domNode`, dan mengambil
* `reactNode`: "React node" yang digunakan untuk me-render HTML yang ada. Biasanya berupa bagian dari JSX seperti `` yang dengan *method* `ReactDOM Server` seperti `renderToPipeableStream()`.
+<<<<<<< HEAD
* **opsional** `options`: Objek dengan opsi untuk akar React.
* **optional** `onCaughtError`: Callback called when React catches an error in an Error Boundary. Called with the `error` caught by the Error Boundary, and an `errorInfo` object containing the `componentStack`.
* **optional** `onUncaughtError`: Callback called when an error is thrown and not caught by an Error Boundary. Called with the `error` that was thrown and an `errorInfo` object containing the `componentStack`.
* **opsional** `onRecoverableError`: *Callback* yang dipanggil saat React berhasil pulih secara otomatis dari kesalahan. Dipanggil dengan `error` yang dikembalikan React, dan obyek `errorInfo` berisi `componentStack`. Beberapa kesalahan yang dapat dipulihkan mungkin akan berisi kesalahan aslinya sebagai `error.cause`.
* **opsional** `identifierPrefix`: Awalan string yang digunakan React untuk ID yang dihasilkan oleh [`useId`.](/reference/react/useId) Berguna untuk menghindari konflik ketika menggunakan beberapa akar pada halaman yang sama. Harus awalan yang sama dengan yang digunakan pada *server*.
+=======
+ * **optional** `onCaughtError`: Callback called when React catches an error in an Error Boundary. Called with the `error` caught by the Error Boundary, and an `errorInfo` object containing the `componentStack`.
+ * **optional** `onUncaughtError`: Callback called when an error is thrown and not caught by an Error Boundary. Called with the `error` that was thrown and an `errorInfo` object containing the `componentStack`.
+ * **optional** `onRecoverableError`: Callback called when React automatically recovers from errors. Called with the `error` React throws, and an `errorInfo` object containing the `componentStack`. Some recoverable errors may include the original error cause as `error.cause`.
+ * **optional** `identifierPrefix`: A string prefix React uses for IDs generated by [`useId`.](/reference/react/useId) Useful to avoid conflicts when using multiple roots on the same page. Must be the same prefix as used on the server.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
#### Kembalian {/*returns*/}
@@ -98,7 +105,11 @@ Aplikasi yang sepenuhnya dibangun dengan React biasanya tidak akan memiliki pang
Hal ini sangat berguna jika akar React DOM node (atau salah satu dari induknya) mungkin akan dihapus dari DOM oleh kode lain. Sebagai contoh, bayangkan sebuah panel *tab* jQuery menghapus *tab* yang tidak aktif dari DOM. Jika sebuah *tab* dihapus, semua yang ada di dalamnya (termasuk akar React di dalamnya) akan dihapus dari DOM juga. Anda perlu memberi tahu React untuk "berhenti" mengelola akar konten yang telah dihapus dengan memanggil `root.unmount`. Jika tidak, komponen-komponen di dalam akar yang dihapus tidak akan dibersihkan dan membebaskan sumber daya seperti langganan.
+<<<<<<< HEAD
Memanggil `root.unmount` akan melepas semua komponen di root dan "melepaskan" React dari akar DOM node, termasuk menghapus semua *event handler* atau *state* di dalam pohon.
+=======
+Calling `root.unmount` will unmount all the components in the root and "detach" React from the root DOM node, including removing any event handlers or state in the tree.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
#### Parameter {/*root-unmount-parameters*/}
@@ -269,7 +280,11 @@ export default function App() {
+<<<<<<< HEAD
Ini hanya berfungsi satu tingkat, dan dimaksudkan sebagai jalan keluar. Jangan terlalu sering menggunakannya. Kecuali jika itu adalah konten teks, React masih belum mencoba untuk memperbaikinya, sehingga mungkin tetap tidak konsisten hingga pembaruan di masa mendatang.
+=======
+This only works one level deep, and is intended to be an escape hatch. Don’t overuse it. React will **not** attempt to patch mismatched text content.
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
---
@@ -373,10 +388,15 @@ export default function App({counter}) {
Tidak lazim untuk memanggil [`root.render`](#root-render) pada *hydrated root*. Biasanya, Anda akan [memperbarui *state*](/reference/react/useState) di dalam salah satu komponen sebagai gantinya.
+<<<<<<< HEAD
### Menunjukkan dialog untuk *error* yang tidak ditangkap {/*show-a-dialog-for-uncaught-errors*/}
+=======
+### Error logging in production {/*error-logging-in-production*/}
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
-
+By default, React will log all errors to the console. To implement your own error reporting, you can provide the optional error handler root options `onUncaughtError`, `onCaughtError` and `onRecoverableError`:
+<<<<<<< HEAD
`onUncaughtError` hanya tersedia di rilis Canary React terbaru.
@@ -571,53 +591,23 @@ export function reportRecoverableError({error, cause, componentStack}) {
```
```js src/index.js active
+=======
+```js [[1, 6, "onCaughtError"], [2, 6, "error", 1], [3, 6, "errorInfo"], [4, 10, "componentStack", 15]]
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
import { hydrateRoot } from "react-dom/client";
-import App from "./App.js";
-import {reportUncaughtError} from "./reportError";
-import "./styles.css";
-import {renderToString} from 'react-dom/server';
+import { reportCaughtError } from "./reportError";
const container = document.getElementById("root");
-const root = hydrateRoot(container, , {
- onUncaughtError: (error, errorInfo) => {
- if (error.message !== 'Known error') {
- reportUncaughtError({
+const root = hydrateRoot(container, {
+ onCaughtError: (error, errorInfo) => {
+ if (error.message !== "Known error") {
+ reportCaughtError({
error,
- componentStack: errorInfo.componentStack
+ componentStack: errorInfo.componentStack,
});
}
- }
-});
-```
-
-```js src/App.js
-import { useState } from 'react';
-
-export default function App() {
- const [throwError, setThrowError] = useState(false);
-
- if (throwError) {
- foo.bar = 'baz';
- }
-
- return (
-
- This error shows the error dialog:
-
-
- );
-}
-```
-
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "^5.0.0"
},
+<<<<<<< HEAD
"main": "/index.js"
}
```
@@ -652,252 +642,116 @@ const root = hydrateRoot(
}
);
root.render();
+=======
+});
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
```
Pengaturan onUncaughtError adalah fungsi yang dipanggil dengan dua argumen:
+<<<<<<< HEAD
1. error yang ditangkap oleh *boundary*.
2. Obyek errorInfo yang berisi componentStack dari *error* tersebut.
Anda dapat menggunakan opsi *root* `onUncaughtError` untuk menunjukkan dialog *error* atau memfilter *error* yang diketahui dari *logging*:
+=======
+1. The error that was thrown.
+2. An errorInfo object that contains the componentStack of the error.
-
+Together with `onUncaughtError` and `onRecoverableError`, you can implement your own error reporting system:
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
-```html index.html hidden
-
-
-
- My app
-
-
-
-
-
-
-
-
-
-
-
-
This error occurred at:
-
-
Call stack:
-
-
-
-
This error is not dismissible.
-
-
-This error will not show the error dialog:This error will show the error dialog:
-
-
-```
-
-```css src/styles.css active
-label, button { display: block; margin-bottom: 20px; }
-html, body { min-height: 300px; }
-
-#error-dialog {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- background-color: white;
- padding: 15px;
- opacity: 0.9;
- text-wrap: wrap;
- overflow: scroll;
-}
-
-.text-red {
- color: red;
-}
-
-.-mb-20 {
- margin-bottom: -20px;
-}
-
-.mb-0 {
- margin-bottom: 0;
-}
-
-.mb-10 {
- margin-bottom: 10px;
-}
-
-pre {
- text-wrap: wrap;
-}
-
-pre.nowrap {
- text-wrap: nowrap;
-}
+
-.hidden {
- display: none;
+```js src/reportError.js
+function reportError({ type, error, errorInfo }) {
+ // The specific implementation is up to you.
+ // `console.error()` is only used for demonstration purposes.
+ console.error(type, error, "Component Stack: ");
+ console.error("Component Stack: ", errorInfo.componentStack);
}
-```
-```js src/reportError.js hidden
-function reportError({ title, error, componentStack, dismissable }) {
- const errorDialog = document.getElementById("error-dialog");
- const errorTitle = document.getElementById("error-title");
- const errorMessage = document.getElementById("error-message");
- const errorBody = document.getElementById("error-body");
- const errorComponentStack = document.getElementById("error-component-stack");
- const errorStack = document.getElementById("error-stack");
- const errorClose = document.getElementById("error-close");
- const errorCause = document.getElementById("error-cause");
- const errorCauseMessage = document.getElementById("error-cause-message");
- const errorCauseStack = document.getElementById("error-cause-stack");
- const errorNotDismissible = document.getElementById("error-not-dismissible");
-
- // Set the title
- errorTitle.innerText = title;
-
- // Display error message and body
- const [heading, body] = error.message.split(/\n(.*)/s);
- errorMessage.innerText = heading;
- if (body) {
- errorBody.innerText = body;
- } else {
- errorBody.innerText = '';
- }
-
- // Display component stack
- errorComponentStack.innerText = componentStack;
-
- // Display the call stack
- // Since we already displayed the message, strip it, and the first Error: line.
- errorStack.innerText = error.stack.replace(error.message, '').split(/\n(.*)/s)[1];
-
- // Display the cause, if available
- if (error.cause) {
- errorCauseMessage.innerText = error.cause.message;
- errorCauseStack.innerText = error.cause.stack;
- errorCause.classList.remove('hidden');
- } else {
- errorCause.classList.add('hidden');
+export function onCaughtErrorProd(error, errorInfo) {
+ if (error.message !== "Known error") {
+ reportError({ type: "Caught", error, errorInfo });
}
- // Display the close button, if dismissible
- if (dismissable) {
- errorNotDismissible.classList.add('hidden');
- errorClose.classList.remove("hidden");
- } else {
- errorNotDismissible.classList.remove('hidden');
- errorClose.classList.add("hidden");
- }
-
- // Show the dialog
- errorDialog.classList.remove("hidden");
}
-export function reportCaughtError({error, cause, componentStack}) {
- reportError({ title: "Caught Error", error, componentStack, dismissable: true});
+export function onUncaughtErrorProd(error, errorInfo) {
+ reportError({ type: "Uncaught", error, errorInfo });
}
-export function reportUncaughtError({error, cause, componentStack}) {
- reportError({ title: "Uncaught Error", error, componentStack, dismissable: false });
-}
-
-export function reportRecoverableError({error, cause, componentStack}) {
- reportError({ title: "Recoverable Error", error, componentStack, dismissable: true });
+export function onRecoverableErrorProd(error, errorInfo) {
+ reportError({ type: "Recoverable", error, errorInfo });
}
```
```js src/index.js active
import { hydrateRoot } from "react-dom/client";
import App from "./App.js";
-import {reportCaughtError} from "./reportError";
-import "./styles.css";
+import {
+ onCaughtErrorProd,
+ onRecoverableErrorProd,
+ onUncaughtErrorProd,
+} from "./reportError";
const container = document.getElementById("root");
-const root = hydrateRoot(container, , {
- onCaughtError: (error, errorInfo) => {
- if (error.message !== 'Known error') {
- reportCaughtError({
- error,
- componentStack: errorInfo.componentStack
- });
- }
- }
+hydrateRoot(container, , {
+ // Keep in mind to remove these options in development to leverage
+ // React's default handlers or implement your own overlay for development.
+ // The handlers are only specfied unconditionally here for demonstration purposes.
+ onCaughtError: onCaughtErrorProd,
+ onRecoverableError: onRecoverableErrorProd,
+ onUncaughtError: onUncaughtErrorProd,
});
```
```js src/App.js
-import { useState } from 'react';
-import { ErrorBoundary } from "react-error-boundary";
+import { Component, useState } from "react";
-export default function App() {
- const [error, setError] = useState(null);
-
- function handleUnknown() {
- setError("unknown");
+function Boom() {
+ foo.bar = "baz";
+}
+
+class ErrorBoundary extends Component {
+ state = { hasError: false };
+
+ static getDerivedStateFromError(error) {
+ return { hasError: true };
}
- function handleKnown() {
- setError("known");
+ render() {
+ if (this.state.hasError) {
+ return Something went wrong.
;
+ }
+ return this.props.children;
}
-
- return (
- <>
- {
- setError(null);
- }}
- >
- {error != null && }
- This error will not show the error dialog:
-
- This error will show the error dialog:
-
-
-
- >
- );
}
-function fallbackRender({ resetErrorBoundary }) {
+export default function App() {
+ const [triggerUncaughtError, settriggerUncaughtError] = useState(false);
+ const [triggerCaughtError, setTriggerCaughtError] = useState(false);
+
return (
-
-
Error Boundary
-
Something went wrong.
-
-
+ <>
+
+ {triggerUncaughtError && }
+
+ {triggerCaughtError && (
+
+
+
+ )}
+ >
);
}
-
-function Throw({error}) {
- if (error === "known") {
- throw new Error('Known error')
- } else {
- foo.bar = 'baz';
- }
-}
```
+<<<<<<< HEAD
```json package.json hidden
{
"dependencies": {
@@ -945,6 +799,9 @@ Anda dapat menggunakan opsi *root* `onUncaughtError` untuk menunjukkan dialog *e
```html index.html hidden
+=======
+```html public/index.html hidden
+>>>>>>> f6d762cbbf958ca45bb8d1d011b31e5289e43a3d
@@ -952,226 +809,12 @@ Anda dapat menggunakan opsi *root* `onUncaughtError` untuk menunjukkan dialog *e
-
-
-
-
-
-
-
-
-
This error occurred at:
-
-
Call stack:
-
-
-
-
This error is not dismissible.
-
-
-Server
+Server content before hydration.
```
-
-```css src/styles.css active
-label, button { display: block; margin-bottom: 20px; }
-html, body { min-height: 300px; }
-
-#error-dialog {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- background-color: white;
- padding: 15px;
- opacity: 0.9;
- text-wrap: wrap;
- overflow: scroll;
-}
-
-.text-red {
- color: red;
-}
-
-.-mb-20 {
- margin-bottom: -20px;
-}
-
-.mb-0 {
- margin-bottom: 0;
-}
-
-.mb-10 {
- margin-bottom: 10px;
-}
-
-pre {
- text-wrap: wrap;
-}
-
-pre.nowrap {
- text-wrap: nowrap;
-}
-
-.hidden {
- display: none;
-}
-```
-
-```js src/reportError.js hidden
-function reportError({ title, error, componentStack, dismissable }) {
- const errorDialog = document.getElementById("error-dialog");
- const errorTitle = document.getElementById("error-title");
- const errorMessage = document.getElementById("error-message");
- const errorBody = document.getElementById("error-body");
- const errorComponentStack = document.getElementById("error-component-stack");
- const errorStack = document.getElementById("error-stack");
- const errorClose = document.getElementById("error-close");
- const errorCause = document.getElementById("error-cause");
- const errorCauseMessage = document.getElementById("error-cause-message");
- const errorCauseStack = document.getElementById("error-cause-stack");
- const errorNotDismissible = document.getElementById("error-not-dismissible");
-
- // Set the title
- errorTitle.innerText = title;
-
- // Display error message and body
- const [heading, body] = error.message.split(/\n(.*)/s);
- errorMessage.innerText = heading;
- if (body) {
- errorBody.innerText = body;
- } else {
- errorBody.innerText = '';
- }
-
- // Display component stack
- errorComponentStack.innerText = componentStack;
-
- // Display the call stack
- // Since we already displayed the message, strip it, and the first Error: line.
- errorStack.innerText = error.stack.replace(error.message, '').split(/\n(.*)/s)[1];
-
- // Display the cause, if available
- if (error.cause) {
- errorCauseMessage.innerText = error.cause.message;
- errorCauseStack.innerText = error.cause.stack;
- errorCause.classList.remove('hidden');
- } else {
- errorCause.classList.add('hidden');
- }
- // Display the close button, if dismissible
- if (dismissable) {
- errorNotDismissible.classList.add('hidden');
- errorClose.classList.remove("hidden");
- } else {
- errorNotDismissible.classList.remove('hidden');
- errorClose.classList.add("hidden");
- }
-
- // Show the dialog
- errorDialog.classList.remove("hidden");
-}
-
-export function reportCaughtError({error, cause, componentStack}) {
- reportError({ title: "Caught Error", error, componentStack, dismissable: true});
-}
-
-export function reportUncaughtError({error, cause, componentStack}) {
- reportError({ title: "Uncaught Error", error, componentStack, dismissable: false });
-}
-
-export function reportRecoverableError({error, cause, componentStack}) {
- reportError({ title: "Recoverable Error", error, componentStack, dismissable: true });
-}
-```
-
-```js src/index.js active
-import { hydrateRoot } from "react-dom/client";
-import App from "./App.js";
-import {reportRecoverableError} from "./reportError";
-import "./styles.css";
-
-const container = document.getElementById("root");
-const root = hydrateRoot(container, , {
- onRecoverableError: (error, errorInfo) => {
- reportRecoverableError({
- error,
- cause: error.cause,
- componentStack: errorInfo.componentStack
- });
- }
-});
-```
-
-```js src/App.js
-import { useState } from 'react';
-import { ErrorBoundary } from "react-error-boundary";
-
-export default function App() {
- const [error, setError] = useState(null);
-
- function handleUnknown() {
- setError("unknown");
- }
-
- function handleKnown() {
- setError("known");
- }
-
- return (
- {typeof window !== 'undefined' ? 'Client' : 'Server'}
- );
-}
-
-function fallbackRender({ resetErrorBoundary }) {
- return (
-
-
Error Boundary
-
Something went wrong.
-
-
- );
-}
-
-function Throw({error}) {
- if (error === "known") {
- throw new Error('Known error')
- } else {
- foo.bar = 'baz';
- }
-}
-```
-
-```json package.json hidden
-{
- "dependencies": {
- "react": "canary",
- "react-dom": "canary",
- "react-scripts": "^5.0.0",
- "react-error-boundary": "4.0.3"
- },
- "main": "/index.js"
-}
-```
-
## Troubleshooting {/*troubleshooting*/}
diff --git a/src/content/reference/react-dom/components/common.md b/src/content/reference/react-dom/components/common.md
index 47e499aca9..73c1b0229b 100644
--- a/src/content/reference/react-dom/components/common.md
+++ b/src/content/reference/react-dom/components/common.md
@@ -247,6 +247,7 @@ Berikut *events* yang aktif pada beberapa sumber daya seperti [`