Component
Component
adalah kelas dasar untuk komponen React yang didefinisikan segabai JavaScript classes. Kelas komponen masih disuport oleh React, tetapi kami tidak merekomendasikan untuk menggunakannya di kode baru.
class Greeting extends Component {
render() {
return <h1>Halo, {this.props.name}!</h1>;
}
}
- Referensi
Component
context
props
refs
state
constructor(props)
componentDidCatch(error, info)
componentDidMount()
componentDidUpdate(prevProps, prevState, snapshot?)
componentWillMount()
componentWillReceiveProps(nextProps)
componentWillUpdate(nextProps, nextState)
componentWillUnmount()
forceUpdate(callback?)
getChildContext()
getSnapshotBeforeUpdate(prevProps, prevState)
render()
setState(nextState, callback?)
shouldComponentUpdate(nextProps, nextState, nextContext)
UNSAFE_componentWillMount()
UNSAFE_componentWillReceiveProps(nextProps, nextContext)
UNSAFE_componentWillUpdate(nextProps, nextState)
static childContextTypes
static contextTypes
static contextType
static defaultProps
static propTypes
static getDerivedStateFromError(error)
static getDerivedStateFromProps(props, state)
- Usage
- Alternatives
Referensi
Component
Untuk mendefinisikan sebuah komponen React sebagai sebuah kelas, extend kelas Component
bawaan dan definisikan render
method:
import { Component } from 'react';
class Greeting extends Component {
render() {
return <h1>Halo, {this.props.name}!</h1>;
}
}
Hanya render
method yang diperlukan, methods yang lain adalah opsional.
Lihat lebih banyak contoh di bawah
context
Context dari sebuah class component tersedia sebagai this.context
. Ini hanya tersedia jika Anda menentukan context yang mana yang ingin Anda terima menggunakan static contextType
(modern) atau static contextTypes
(deprecated).
Class component hanya bisa membaca satu context pada satu waktu.
class Button extends Component {
static contextType = ThemeContext;
render() {
const theme = this.context;
const className = 'button-' + theme;
return (
<button className={className}>
{this.props.children}
</button>
);
}
}
props
props yang dioper ke sebuah class component tersedia sebagai this.props
.
class Greeting extends Component {
render() {
return <h1>Halo, {this.props.name}!</h1>;
}
}
<Greeting name="Taylor" />
refs
Memungkinkan Anda mengakses legacy string refs pada komponen ini.
state
State dari class component tersedia sebagai this.state
. Field state harus berupa objek. Jangan mengubah state secara langsung. Jika Anda ingin mengubah state, panggil setState
dengan state baru.
class Counter extends Component {
state = {
age: 42,
};
handleAgeChange = () => {
this.setState({
age: this.state.age + 1
});
};
render() {
return (
<>
<button onClick={this.handleAgeChange}>
Increment age
</button>
<p>You are {this.state.age}.</p>
</>
);
}
}
constructor(props)
Constructor dijalankan sebelum class component Anda dipasang (ditambahkan ke layar). Biasanya, sebuah constructor hanya digunakan untuk dua tujuan dalam React. Ini memungkinkan Anda mendeklarasikan state dan bind class methods Anda ke class instance:
class Counter extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// ...
}
Jika Anda menggunakan sintaksis JavaScript modern, constructors jarang diperlukan. Sebagai gantinya, Anda dapat menulis ulang kode di atas menggunakan public class field syntax yang didukung oleh browser modern dan alat seperti Babel:
class Counter extends Component {
state = { counter: 0 };
handleClick = () => {
// ...
}
Sebuah constructor sebaiknya tidak mengandung side effects atau subscriptions.
Parameters
props
: Props awal komponen.
Returns
constructor
seharusnya tidak mengembalikan apapun.
Caveats
-
Jangan menjalankan side effects atau subscriptions dalam constructor. Sebagai gantinya, gunakan
componentDidMount
untuk itu. -
Dalam sebuah constructor, Anda perlu memanggil
super(props)
sebelum pernyataan lainnya. Jika Anda tidak melakukannya,this.props
akan menjadiundefined
saat constructor berjalan, yang dapat membingungkan dan menyebabkan bug. -
Constructor adalah satu-satunya tempat di mana Anda dapat langsung mengisi nilai
this.state
. Pada semua metode lainnya, Anda perlu menggunakanthis.setState()
sebagai gantinya. Jangan memanggilsetState
di dalam constructor. -
Ketika Anda menggunakan pe-render-an di server, constructor juga akan dijalankan di server, diikuti oleh metode
render
. Namun, lifecycle methods seperticomponentDidMount
ataucomponentWillUnmount
tidak akan dijalankan di server. -
Ketika Strict Mode diaktifkan, React akan memanggil
constructor
dua kali dalam pengembangan kemudian membuang salah satu instances. Ini membantu Anda memperhatikan side effects yang tidak disengaja yang perlu dipindahkan dariconstructor
.
componentDidCatch(error, info)
Jika Anda mendefinisikan componentDidCatch
, React akan memanggilnya ketika beberapa komponen anak(termasuk anak-anak yang jauh) melempar sebuah kesalahan saat rendering. Hal ini memungkinkan Anda untuk mencatat kesalahan tersebut ke error reporting service di produksi.
Biasanya, digunakan bersama dengan static getDerivedStateFromError
yang memungkinkan Anda memperbarui state sebagai respons terhadap kesalahan dan menampilkan pesan kesalahan kepada pengguna. Komponen dengan metode-metode ini disebut sebagai error boundary.
Parameters
-
error
: Error yang dilempar. Pada praktiknya, biasanya akan berupa sebuah instance dariError
tetapi ini tidak dijamin karena JavaScript memungkinkan untukthrow
nilai apa pun, termasuk string atau bahkan null. -
info
: Objek yang berisi informasi tambahan tentang error. FieldcomponentStack
berisi jejak tumpukan(stack trace) dengan komponen yang melempar kesalahan, serta nama-nama dan lokasi sumber dari semua komponen induknya. Di produksi, nama komponennya akan di-minified. Jika Anda mengatur error reporting di produksi, Anda dapat mendekode jejak tumpukan(stack trace) komponen menggunakan sourcemaps dengan cara yang sama seperti yang Anda lakukan untuk jejak tumpukan(stack trace) kesalahan JavaScript biasa.
Returns
componentDidCatch
seharusnya tidak mengembalikan apapun.
Caveats
-
Di masa lalu, umumnya memanggil
setState
di dalamcomponentDidCatch
untuk memperbarui antarmuka pengguna(UI) dan menampilkan pesan kesalahan pengganti. Ini sudah ditinggalkan karena mendefinisikanstatic getDerivedStateFromError
. -
Build produksi dan pengembangan dari React sedikit berbeda dalam cara
componentDidCatch
menangani kesalahan. Pada pengembangan, kesalahan akan naik kewindow
, yang berartiwindow.onerror
atauwindow.addEventListener('error', callback)
akan menangkap kesalahan yang telah ditangkap olehcomponentDidCatch
. Pada produksi, sebaliknya, kesalahan tidak akan naik, yang berarti penangan kesalahan induk hanya akan menerima kesalahan yang tidak ditangkap secara eksplisit olehcomponentDidCatch
.
componentDidMount()
Jika Anda mendefinisikan metode componentDidMount
, React akan memanggilnya ketika komponen Anda ditambahkan*(mounted)* ke layar. Ini adalah tempat umum untuk memulai pengambilan data, menyiapkan subscriptions, atau memanipulasi DOM nodes.
Jika Anda mengimplementasikan componentDidMount
, biasanya Anda juga perlu mengimplementasikan lifecycle methods lainnya untuk menghindari bug. Sebagai contoh, jika componentDidMount
membaca sebuah state atau props, Anda juga harus mengimplementasikan componentDidUpdate
untuk menangani perubahan mereka, dan componentWillUnmount
untuk membersihkan apa pun yang dilakukan oleh componentDidMount
.
class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};
componentDidMount() {
this.setupConnection();
}
componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}
componentWillUnmount() {
this.destroyConnection();
}
// ...
}
Parameters
componentDidMount
tidak mengambil parameter apa pun.
Returns
componentDidMount
seharusnya tidak mengembalikan apapun.
Caveats
-
Ketika Strict Mode aktif, di pengembangan React kan memanggil
componentDidMount
, kemudian segera memanggilcomponentWillUnmount
, dan kemudian memanggilcomponentDidMount
lagi. Ini membantu Anda melihai jika Anda lupa untuk mengimplementasikancomponentWillUnmount
atau jika logikanya tidak sepenuhnya “mencerminkan” apa yang dilakukan olehcomponentDidMount
. -
Meskipun Anda dapat langsung memanggil
setState
dicomponentDidMount
, sebaiknya hindari hal itu jika bisa. Ini akan memicu render-ing ekstra, tetapi itu akan terjadi sebelum browser memperbarui layar. Ini menjamin bahwa meskipunrender
akan dipanggil dua kali dalam kasus ini, pengguna tidak akan melihat state perantara. Gunakan pola ini dengan hati-hati karena sering menyebabkan masalah performa. Dalam kebanyakan kasus, Anda seharusnya dapat menetapkan state awal diconstructor
sebagai gantinya. Namun, dalam beberapa kasus seperti modal dan tooltip ketika Anda perlu mengukur sebuah DOM node sebelum me-render sesuatu yang bergantung pada ukuran atau posisinya.
componentDidUpdate(prevProps, prevState, snapshot?)
Jika Anda mendefinisikan metode componentDidUpdate
, React akan memanggilnya segera setelah komponen Anda di-render ulang dengan prop atau state yang diperbarui. Metode ini tidak dipanggil saat render awal.
Anda dapat menggunakannya untuk memanipulasi DOM setelah pembaruan. Ini juga tempat umum untuk melakukan permintaan jaringan selama Anda membandingkan prop saat ini dengan prop sebelumnya (misalnya, permintaan jaringan mungkin tidak diperlukan jika prop tidak berubah). Biasanya, Anda akan menggunakannya bersama dengan componentDidMount
dan componentWillUnmount
:
class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};
componentDidMount() {
this.setupConnection();
}
componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}
componentWillUnmount() {
this.destroyConnection();
}
// ...
}
Parameters
-
prevProps
: Props sebelum update. MembandingkanprevProps
kethis.props
untuk menentukan apa yang berubah. -
prevState
: State sebelum update. MembandingkanprevState
kethis.state
untuk menentukan apa yang berubah. -
snapshot
: Jika Anda mengimplementasikangetSnapshotBeforeUpdate
,snapshot
akan berisi nilai yang Anda kembalikan dari metode tersebut. Jika tidak, nilainya akanundefined
.
Returns
componentDidUpdate
seharusnya tidak mengembalikan apapun.
Caveats
-
componentDidUpdate
tidak akan dipanggil jikashouldComponentUpdate
didefinisikan dan mengembalikanfalse
. -
Logika di dalam
componentDidUpdate
biasanya harus dibungkus dalam kondisi yang membandingkanthis.props
denganprevProps
, danthis.state
denganprevState
. Jika tidak, ada risiko terjadi perulangan tak terbatas. -
Meskipun Anda dapat memanggil
setState
langsung di dalamcomponentDidUpdate
, sebaiknya hindari hal itu jika memungkinkan. Ini akan memicu render tambahan, tetapi akan terjadi sebelum browser memperbarui tampilan. Ini menjamin bahwa meskipunrender
akan dipanggil dua kali dalam kasus ini, pengguna tidak akan melihat intermediate state. Pola ini sering menyebabkan isu performance, tetapi mungkin diperlukan untuk kasus-kasus langka seperti modal dan tooltip ketika Anda perlu mengukur node DOM sebelum me-render sesuatu yang bergantung pada ukuran atau posisinya.
componentWillMount()
componentWillReceiveProps(nextProps)
componentWillUpdate(nextProps, nextState)
componentWillUnmount()
Jika Anda mendefinisikan metode componentWillUnmount
, React akan memanggilnya sebelum komponen Anda dihapus (unmounted) dari layar. Ini adalah tempat umum untuk membatalkan pengambilan data atau menghapus langganan.
Logika di dalam componentWillUnmount
harus “mencerminkan” logika di dalam componentDidMount
. Sebagai contoh, jika componentDidMount
mempersiapkan langganan, componentWillUnmount
harus membersihkan langganan itu. Jika logika pembersihan di componentWillUnmount
membaca beberapa props atau state, Anda biasanya juga perlu menerapkan componentDidUpdate
untuk membersihkan sumber daya (seperti langganan) yang sesuai dengan props dan state lama.
class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};
componentDidMount() {
this.setupConnection();
}
componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}
componentWillUnmount() {
this.destroyConnection();
}
// ...
}
Parameters
componentWillUnmount
tidak mengambil parameter apapun.
Returns
componentWillUnmount
seharusnya tidak mengembalikan apapun.
Caveats
- Ketika Strict Mode aktif, pada development React akan memanggil
componentDidMount
, kemudian segera memanggilcomponentWillUnmount
, dan kemudian memanggilcomponentDidMount
lagi. Ini membantu Anda memperhatikan jika Anda lupa menerapkancomponentWillUnmount
atau jika logikanya tidak sepenuhnya “mencerminkan” apa yangcomponentDidMount
lakukan.
forceUpdate(callback?)
Memaksa komponen untuk me-render ulang.
Biasanya, ini tidak perlu. Jika metode render
komponen Anda hanya baca(only reads) dari this.props
, this.state
, atau this.context
, akan me-render ulang otomatis ketika Anda memanggil setState
di dalam komponen Anda atau salah satu dari parent. Namun, Jika metode render
komponen Anda membaca secara langsung dari sumber data eksternal, Anda harus memberi tahu React untuk memperbarui antarmuka pengguna saat sumber data itu berubah. Itulah yang forceUpdate
memungkinkan Anda melakukannya.
Cobalah untuk menghindari semua penggunaan forceUpdate
dan hanya membaca dari this.props
dan this.state
pada render
.
Parameters
- optional
callback
Jika ditentukan, React akan memanggilcallback
yang Anda berikan setelah pembaruan dilakukan.
Returns
forceUpdate
tidak mengembalikan apapun.
Caveats
- Jika Anda memanggil
forceUpdate
, React akan me-render ulang tanpa memanggilshouldComponentUpdate
.
getChildContext()
Memungkinkan Anda menentukan nilai untuk legacy context yang disediakan oleh komponen ini.
getSnapshotBeforeUpdate(prevProps, prevState)
Jika Anda mengimplementasikan getSnapshotBeforeUpdate
, React akan segera memanggilnya sebelum React memperbarui DOM. Ini memungkinkan komponen Anda untuk menangkap beberapa informasi dari DOM (e.g. posisi scroll) sebelum berpotensi diubah. Nilai apa pun yang dikembalikan oleh lifecycle method ini akan diteruskan sebagai parameter ke componentDidUpdate
.
Misalnya, Anda dapat menggunakannya di UI seperti utas obrolan yang perlu mempertahankan posisi scroll-nya selama pembaruan:
class ScrollingList extends React.Component {
constructor(props) {
super(props);
this.listRef = React.createRef();
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// Are we adding new items to the list?
// Capture the scroll position so we can adjust scroll later.
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// If we have a snapshot value, we've just added new items.
// Adjust scroll so these new items don't push the old ones out of view.
// (snapshot here is the value returned from getSnapshotBeforeUpdate)
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}
render() {
return (
<div ref={this.listRef}>{/* ...contents... */}</div>
);
}
}
Pada contoh di atas, penting untuk membaca properti scrollHeight
secara langsung di getSnapshotBeforeUpdate
. Tidak aman untuk membacanya di render
, UNSAFE_componentWillReceiveProps
, atau UNSAFE_componentWillUpdate
karena ada potensi jeda waktu antara pemanggilan metode ini dan React memperbarui DOM.
Parameters
-
prevProps
: Props sebelum pembaharuan. MembandingkanprevProps
kethis.props
untuk menentukan apa yang berubah. -
prevState
: State sebelum pembaharuan. MembandingkanprevState
kethis.state
untuk menentukan apa yang berubah.
Returns
Anda harus mengembalikan nilai snapshot dari jenis apa pun yang Anda inginkan, atau null
. Nilai yang Anda kembalikan akan diteruskan sebagai argumen ketiga pada componentDidUpdate
.
Caveats
getSnapshotBeforeUpdate
tidak akan dipanggil jikashouldComponentUpdate
didefinisikan dan mengembalikanfalse
.
render()
Metode render
adalah satu-satunya metode yang diperlukan dalam class component.
Metode render
harus menentukan apa yang ingin Anda tampilkan di layar, misalnya:
import { Component } from 'react';
class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
React dapat memanggil render
kapan saja, jadi Anda tidak boleh berasumsi bahwa itu berjalan pada waktu tertentu. Biasanya, metode render
harus mengembalikan sebagian dari JSX, tetapi beberapa jenis return lainnya (seperti strings) didukung. Untuk menghitung JSX yang dikembalikan, metode render
dapat membacathis.props
, this.state
, dan this.context
.
Anda harus menulis metode render
sebagai pure function, artinya ia harus mengembalikan hasil yang sama jika props, state, dan context-nya sama. Itu juga tidak boleh mengandung side effects (seperti menyiapkan subscriptions) atau interaksi dengan API peramban. Side effects harus terjadi baik dalam event handlers atau metode seperti componentDidMount
.
Parameters
-
prevProps
: Props sebelum pembaruan. BandingkanprevProps
kethis.props
untuk menentukan apa yang berubah. -
prevState
: State sebelum pembaruan. BandingkanprevState
kethis.state
untuk menentukan apa yang berubah.
Returns
render
dapat mengembalikan node React apa pun yang valid. Ini termasuk elemen-elemen React seperti <div />
, strings, numbers, portals, nodes kosong (null
, undefined
, true
, dan false
), dan arrays dari React nodes.
Caveats
-
render
harus ditulis sebagai pure function dari props, state, dan context. Seharusnya tidak memiliki side effects. -
render
tidak akan dipanggil jikashouldComponentUpdate
didefinisikan dan mengembalikanfalse
. -
Ketika Strict Mode aktif, React akan memanggil
render
dua kali dalam development dan kemudian membuang salah satu hasilnya. Ini membantu Anda melihat efek samping yang tidak disengaja yang perlu dipindahkan dari metoderender
. -
Tidak ada korespondensi one-to-one antara panggilan
render
dan panggilancomponentDidMount
atau panggilancomponentDidUpdate
. Beberapa hasil panggilanrender
mungkin dibuang oleh React jika bermanfaat.
setState(nextState, callback?)
Memanggil setState
untuk mengupdate state dari komponen React Anda.
class Form extends Component {
state = {
name: 'Taylor',
};
handleNameChange = (e) => {
const newName = e.target.value;
this.setState({
name: newName
});
}
render() {
return (
<>
<input value={this.state.name} onChange={this.handleNameChange} />
<p>Hello, {this.state.name}.
</>
);
}
}
setState
mengantrekan perubahan ke state komponen. Ini memberi tahu React bahwa komponen ini dan turunannya perlu di-render ulang dengan state baru. Ini adalah cara utama Anda memperbarui antarmuka pengguna sebagai respons terhadap interaksi.
Anda juga dapat meneruskan fungsi ke setState
. Ini memungkinkan Anda memperbarui state berdasarkan state sebelumnya:
handleIncreaseAge = () => {
this.setState(prevState => {
return {
age: prevState.age + 1
};
});
}
Anda tidak harus melakukan ini, tetapi akan berguna jika Anda ingin memperbarui state beberapa kali selama event yang sama.
Parameters
-
nextState
: Baik objek atau fungsi.- Jika Anda meneruskan objek sebagai
nextState
, objek tersebut akan digabungkan secara dangkal ke dalamthis.state
. - Jika Anda meneruskan fungsi sebagai
nextState
, fungsi tersebut akan diperlakukan sebagai updater function. Itu harus murni, harus mengambilstate
danprops
yang tertunda sebagai argumen, dan harus mengembalikan objek untuk digabungkan secara dangkal ke dalamthis.state
. React akan menempatkan fungsi pembaru Anda dalam antrean dan merender ulang komponen Anda. Selama render berikutnya, React akan menghitung state selanjutnya dengan menerapkan semua pembaruan yang antri ke state sebelumnya.
- Jika Anda meneruskan objek sebagai
-
opsional
callback
: Jika ditentukan, React akan memanggilcallback
yang Anda berikan setelah pembaruan dilakukan.
Returns
setState
tidak mengembalikan apapun.
Caveats
-
Pikirkan
setState
sebagai permintaan daripada perintah langsung untuk memperbarui komponen. Ketika beberapa komponen memperbarui state-nya sebagai respons terhadap suatu event, React akan mengelompokkan pembaruannya dan merendernya kembali bersama-sama dalam satu lintasan di akhir event. Dalam kasus yang jarang terjadi saat Anda perlu memaksa pembaruan state tertentu untuk diterapkan secara sinkron, Anda dapat menggabungkannya dalamflushSync
, tetapi ini dapat mengganggu kinerja. -
setState
tidak segera memperbaruithis.state
. Hal ini membuat pembacaanthis.state
tepat setelah memanggilsetState
menjadi potensial jebakan. Sebagai gantinya, gunakancomponentDidUpdate
atau argumen setStatecallback
, yang keduanya dijamin akan aktif setelah pembaruan diterapkan. Jika Anda perlu menyetel state berdasarkan state sebelumnya, Anda dapat meneruskan fungsi kenextState
seperti yang dijelaskan di atas.
shouldComponentUpdate(nextProps, nextState, nextContext)
Jika Anda mendefinisikan shouldComponentUpdate
, React akan memanggilnya untuk menentukan apakah render ulang dapat dilewati.
Jika Anda yakin ingin menulisnya dengan tangan, Anda dapat membandingkan this.props
dengan nextProps
dan this.state
dengan nextState
dan mengembalikan false
untuk memberi tahu React bahwa pembaruan dapat dilewati.
class Rectangle extends Component {
state = {
isHovered: false
};
shouldComponentUpdate(nextProps, nextState) {
if (
nextProps.position.x === this.props.position.x &&
nextProps.position.y === this.props.position.y &&
nextProps.size.width === this.props.size.width &&
nextProps.size.height === this.props.size.height &&
nextState.isHovered === this.state.isHovered
) {
// Nothing has changed, so a re-render is unnecessary
return false;
}
return true;
}
// ...
}
React memanggil shouldComponentUpdate
sebelum render-ing ketika props baru atau state sedang diterima. Default true
. Metode ini tidak dipanggil untuk render awal atau saat forceUpdate
digunakan.
Parameters
nextProps
: Props berikutnya yang akan dirender oleh komponen. BandingkannextProps
denganthis.props
untuk menentukan apa yang berubah.nextState
: State berikutnya yang akan di-render oleh komponen. BandingkannextState
denganthis.state
untuk menentukan apa yang berubah.nextContext
: Konteks berikutnya yang akan di-render oleh komponen. BandingkannextContext
denganthis.context
untuk menentukan apa yang berubah. Hanya tersedia jika Anda menetapkanstatic contextType
(modern) ataustatic contextTypes
(legacy).
Returns
Mengembalikan true
jika Anda ingin komponen di-render ulang. Itu merupakan perilaku default.
Mengembalikan false
untuk memberitahu React bahwa render ulang dapat dilewati.
Caveats
-
Metode ini hanya ada sebagai pengoptimalan kinerja. Jika komponen Anda rusak tanpanya, perbaiki terlebih dahulu.
-
Pertimbangkan untuk menggunakan
PureComponent
daripada menulisshouldComponentUpdate
secara manual.PureComponent
secara dangkal membandingkan props dan state, dan mengurangi kemungkinan Anda melewati pembaruan yang diperlukan. -
Kami tidak menyarankan melakukan pemeriksaan kesetaraan mendalam atau menggunakan
JSON.stringify
dishouldComponentUpdate
. Itu membuat kinerja tidak dapat diprediksi dan bergantung pada struktur data setiap prop dan state. Dalam kasus terbaik, Anda berisiko memperkenalkan henti selama beberapa detik pada aplikasi Anda, dan dalam kasus terburuk Anda berisiko membuatnya crash. -
Mengembalikan
false
tidak mencegah komponen turunan dari render-ing ulang ketika state mereka berubah. -
Mengembalikan
false
tidak menjamin bahwa komponen tidak akan di-render ulang. React akan menggunakan nilai yang dikembalikan sebagai petunjuk tetapi mungkin masih memilih untuk me-render ulang komponen Anda jika masuk akal untuk dilakukan karena alasan lain.
UNSAFE_componentWillMount()
Jika Anda mendefinisikan UNSAFE_componentWillMount
, React akan memanggilnya segera setelah constructor
. Itu hanya ada karena alasan historis dan tidak boleh digunakan dalam kode baru apa pun. Sebagai gantinya, gunakan salah satu alternatif:
- Untuk menginisialisasi state, deklarasikan
state
sebagai bidang kelas atau setelthis.state
di dalamkonstruktor
. - Jika Anda perlu menjalankan efek samping atau menyiapkan langganan, pindahkan logika tersebut ke
componentDidMount
sebagai gantinya.
Lihat contoh migrasi dari unsafe lifecycles.
Parameters
UNSAFE_componentWillMount
tidak menggunakan parameter apa pun.
Returns
UNSAFE_componentWillMount
seharusnya tidak mengembalikan apa pun.
Caveats
-
UNSAFE_componentWillMount
tidak akan dipanggil jika komponen mengimplementasikanstatic getDerivedStateFromProps
ataugetSnapshotBeforeUpdate
. -
Terlepas dari namanya,
UNSAFE_componentWillMount
tidak menjamin bahwa komponen akan dipasang jika aplikasi Anda menggunakan fitur React modern sepertiSuspense
. Jika upaya render ditangguhkan (misalnya, karena kode untuk beberapa komponen anak belum dimuat), React akan membuang pohon yang sedang berjalan dan mencoba membangun komponen dari awal selama upaya berikutnya. Inilah mengapa metode ini “tidak aman”. Kode yang bergantung pada pemasangan (seperti menambahkan langganan) harus masuk kecomponentDidMount
. -
UNSAFE_componentWillMount
adalah satu-satunya metode siklus hidup yang berjalan selama server rendering. Untuk semua tujuan praktis, ini identik denganconstructor
, sehingga Anda harus menggunakankonstruktor
untuk jenis logika ini.
UNSAFE_componentWillReceiveProps(nextProps, nextContext)
If you define UNSAFE_componentWillReceiveProps
, React will call it when the component receives new props. It only exists for historical reasons and should not be used in any new code. Instead, use one of the alternatives:
- If you need to run a side effect (for example, fetch data, run an animation, or reinitialize a subscription) in response to prop changes, move that logic to
componentDidUpdate
instead. - If you need to avoid re-computing some data only when a prop changes, use a memoization helper instead.
- If you need to “reset” some state when a prop changes, consider either making a component fully controlled or fully uncontrolled with a key instead.
- If you need to “adjust” some state when a prop changes, check whether you can compute all the necessary information from props alone during rendering. If you can’t, use
static getDerivedStateFromProps
instead.
See examples of migrating away from unsafe lifecycles.
Parameters
nextProps
: The next props that the component is about to receive from its parent component. ComparenextProps
tothis.props
to determine what changed.nextContext
: The next props that the component is about to receive from the closest provider. ComparenextContext
tothis.context
to determine what changed. Only available if you specifystatic contextType
(modern) orstatic contextTypes
(legacy).
Returns
UNSAFE_componentWillReceiveProps
should not return anything.
Caveats
-
UNSAFE_componentWillReceiveProps
will not get called if the component implementsstatic getDerivedStateFromProps
orgetSnapshotBeforeUpdate
. -
Despite its naming,
UNSAFE_componentWillReceiveProps
does not guarantee that the component will receive those props if your app uses modern React features likeSuspense
. If a render attempt is suspended (for example, because the code for some child component has not loaded yet), React will throw the in-progress tree away and attempt to construct the component from scratch during the next attempt. By the time of the next render attempt, the props might be different. This is why this method is “unsafe”. Code that should run only for committed updates (like resetting a subscription) should go intocomponentDidUpdate
. -
UNSAFE_componentWillReceiveProps
does not mean that the component has received different props than the last time. You need to comparenextProps
andthis.props
yourself to check if something changed. -
React doesn’t call
UNSAFE_componentWillReceiveProps
with initial props during mounting. It only calls this method if some of component’s props are going to be updated. For example, callingsetState
doesn’t generally triggerUNSAFE_componentWillReceiveProps
inside the same component.
UNSAFE_componentWillUpdate(nextProps, nextState)
If you define UNSAFE_componentWillUpdate
, React will call it before rendering with the new props or state. It only exists for historical reasons and should not be used in any new code. Instead, use one of the alternatives:
- If you need to run a side effect (for example, fetch data, run an animation, or reinitialize a subscription) in response to prop or state changes, move that logic to
componentDidUpdate
instead. - If you need to read some information from the DOM (for example, to save the current scroll position) so that you can use it in
componentDidUpdate
later, read it insidegetSnapshotBeforeUpdate
instead.
See examples of migrating away from unsafe lifecycles.
Parameters
nextProps
: The next props that the component is about to render with. ComparenextProps
tothis.props
to determine what changed.nextState
: The next state that the component is about to render with. ComparenextState
tothis.state
to determine what changed.
Returns
UNSAFE_componentWillUpdate
should not return anything.
Caveats
-
UNSAFE_componentWillUpdate
will not get called ifshouldComponentUpdate
is defined and returnsfalse
. -
UNSAFE_componentWillUpdate
will not get called if the component implementsstatic getDerivedStateFromProps
orgetSnapshotBeforeUpdate
. -
It’s not supported to call
setState
(or any method that leads tosetState
being called, like dispatching a Redux action) duringcomponentWillUpdate
. -
Despite its naming,
UNSAFE_componentWillUpdate
does not guarantee that the component will update if your app uses modern React features likeSuspense
. If a render attempt is suspended (for example, because the code for some child component has not loaded yet), React will throw the in-progress tree away and attempt to construct the component from scratch during the next attempt. By the time of the next render attempt, the props and state might be different. This is why this method is “unsafe”. Code that should run only for committed updates (like resetting a subscription) should go intocomponentDidUpdate
. -
UNSAFE_componentWillUpdate
does not mean that the component has received different props or state than the last time. You need to comparenextProps
withthis.props
andnextState
withthis.state
yourself to check if something changed. -
React doesn’t call
UNSAFE_componentWillUpdate
with initial props and state during mounting.
static childContextTypes
Lets you specify which legacy context is provided by this component.
static contextTypes
Lets you specify which legacy context is consumed by this component.
static contextType
If you want to read this.context
from your class component, you must specify which context it needs to read. The context you specify as the static contextType
must be a value previously created by createContext
.
class Button extends Component {
static contextType = ThemeContext;
render() {
const theme = this.context;
const className = 'button-' + theme;
return (
<button className={className}>
{this.props.children}
</button>
);
}
}
static defaultProps
You can define static defaultProps
to set the default props for the class. They will be used for undefined
and missing props, but not for null
props.
For example, here is how you define that the color
prop should default to 'blue'
:
class Button extends Component {
static defaultProps = {
color: 'blue'
};
render() {
return <button className={this.props.color}>click me</button>;
}
}
If the color
prop is not provided or is undefined
, it will be set by default to 'blue'
:
<>
{/* this.props.color is "blue" */}
<Button />
{/* this.props.color is "blue" */}
<Button color={undefined} />
{/* this.props.color is null */}
<Button color={null} />
{/* this.props.color is "red" */}
<Button color="red" />
</>
static propTypes
You can define static propTypes
together with the prop-types
library to declare the types of the props accepted by your component. These types will be checked during rendering and in development only.
import PropTypes from 'prop-types';
class Greeting extends React.Component {
static propTypes = {
name: PropTypes.string
};
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
static getDerivedStateFromError(error)
If you define static getDerivedStateFromError
, React will call it when a child component (including distant children) throws an error during rendering. This lets you display an error message instead of clearing the UI.
Typically, it is used together with componentDidCatch
which lets you send the error report to some analytics service. A component with these methods is called an error boundary.
Parameters
error
: The error that was thrown. In practice, it will usually be an instance ofError
but this is not guaranteed because JavaScript allows tothrow
any value, including strings or evennull
.
Returns
static getDerivedStateFromError
should return the state telling the component to display the error message.
Caveats
static getDerivedStateFromError
should be a pure function. If you want to perform a side effect (for example, to call an analytics service), you need to also implementcomponentDidCatch
.
static getDerivedStateFromProps(props, state)
If you define static getDerivedStateFromProps
, React will call it right before calling render
, both on the initial mount and on subsequent updates. It should return an object to update the state, or null
to update nothing.
This method exists for rare use cases where the state depends on changes in props over time. For example, this Form
component resets the email
state when the userID
prop changes:
class Form extends Component {
state = {
email: this.props.defaultEmail,
prevUserID: this.props.userID
};
static getDerivedStateFromProps(props, state) {
// Any time the current user changes,
// Reset any parts of state that are tied to that user.
// In this simple example, that's just the email.
if (props.userID !== state.prevUserID) {
return {
prevUserID: props.userID,
email: props.defaultEmail
};
}
return null;
}
// ...
}
Note that this pattern requires you to keep a previous value of the prop (like userID
) in state (like prevUserID
).
Parameters
props
: The next props that the component is about to render with.state
: The next state that the component is about to render with.
Returns
static getDerivedStateFromProps
return an object to update the state, or null
to update nothing.
Caveats
-
This method is fired on every render, regardless of the cause. This is different from
UNSAFE_componentWillReceiveProps
, which only fires when the parent causes a re-render and not as a result of a localsetState
. -
This method doesn’t have access to the component instance. If you’d like, you can reuse some code between
static getDerivedStateFromProps
and the other class methods by extracting pure functions of the component props and state outside the class definition.
Usage
Defining a class component
To define a React component as a class, extend the built-in Component
class and define a render
method:
import { Component } from 'react';
class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
React will call your render
method whenever it needs to figure out what to display on the screen. Usually, you will return some JSX from it. Your render
method should be a pure function: it should only calculate the JSX.
Similarly to function components, a class component can receive information by props from its parent component. However, the syntax for reading props is different. For example, if the parent component renders <Greeting name="Taylor" />
, then you can read the name
prop from this.props
, like this.props.name
:
import { Component } from 'react'; class Greeting extends Component { render() { return <h1>Hello, {this.props.name}!</h1>; } } export default function App() { return ( <> <Greeting name="Sara" /> <Greeting name="Cahal" /> <Greeting name="Edite" /> </> ); }
Note that Hooks (functions starting with use
, like useState
) are not supported inside class components.
Adding state to a class component
To add state to a class, assign an object to a property called state
. To update state, call this.setState
.
import { Component } from 'react'; export default class Counter extends Component { state = { name: 'Taylor', age: 42, }; handleNameChange = (e) => { this.setState({ name: e.target.value }); } handleAgeChange = () => { this.setState({ age: this.state.age + 1 }); }; render() { return ( <> <input value={this.state.name} onChange={this.handleNameChange} /> <button onClick={this.handleAgeChange}> Increment age </button> <p>Hello, {this.state.name}. You are {this.state.age}.</p> </> ); } }
Adding lifecycle methods to a class component
There are a few special methods you can define on your class.
If you define the componentDidMount
method, React will call it when your component is added (mounted) to the screen. React will call componentDidUpdate
after your component re-renders due to changed props or state. React will call componentWillUnmount
after your component has been removed (unmounted) from the screen.
If you implement componentDidMount
, you usually need to implement all three lifecycles to avoid bugs. For example, if componentDidMount
reads some state or props, you also have to implement componentDidUpdate
to handle their changes, and componentWillUnmount
to clean up whatever componentDidMount
was doing.
For example, this ChatRoom
component keeps a chat connection synchronized with props and state:
import { Component } from 'react'; import { createConnection } from './chat.js'; export default class ChatRoom extends Component { state = { serverUrl: 'https://localhost:1234' }; componentDidMount() { this.setupConnection(); } componentDidUpdate(prevProps, prevState) { if ( this.props.roomId !== prevProps.roomId || this.state.serverUrl !== prevState.serverUrl ) { this.destroyConnection(); this.setupConnection(); } } componentWillUnmount() { this.destroyConnection(); } setupConnection() { this.connection = createConnection( this.state.serverUrl, this.props.roomId ); this.connection.connect(); } destroyConnection() { this.connection.disconnect(); this.connection = null; } render() { return ( <> <label> Server URL:{' '} <input value={this.state.serverUrl} onChange={e => { this.setState({ serverUrl: e.target.value }); }} /> </label> <h1>Welcome to the {this.props.roomId} room!</h1> </> ); } }
Note that in development when Strict Mode is on, React will call componentDidMount
, immediately call componentWillUnmount
, and then call componentDidMount
again. This helps you notice if you forgot to implement componentWillUnmount
or if its logic doesn’t fully “mirror” what componentDidMount
does.
Catching rendering errors with an error boundary
By default, if your application throws an error during rendering, React will remove its UI from the screen. To prevent this, you can wrap a part of your UI into an error boundary. An error boundary is a special component that lets you display some fallback UI instead of the part that crashed—for example, an error message.
To implement an error boundary component, you need to provide static getDerivedStateFromError
which lets you update state in response to an error and display an error message to the user. You can also optionally implement componentDidCatch
to add some extra logic, for example, to log the error to an analytics service.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, info) {
// Example "componentStack":
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
logErrorToMyService(error, info.componentStack);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return this.props.fallback;
}
return this.props.children;
}
}
Then you can wrap a part of your component tree with it:
<ErrorBoundary fallback={<p>Something went wrong</p>}>
<Profile />
</ErrorBoundary>
If Profile
or its child component throws an error, ErrorBoundary
will “catch” that error, display a fallback UI with the error message you’ve provided, and send a production error report to your error reporting service.
You don’t need to wrap every component into a separate error boundary. When you think about the granularity of error boundaries, consider where it makes sense to display an error message. For example, in a messaging app, it makes sense to place an error boundary around the list of conversations. It also makes sense to place one around every individual message. However, it wouldn’t make sense to place a boundary around every avatar.
Alternatives
Migrating a simple component from a class to a function
Typically, you will define components as functions instead.
For example, suppose you’re converting this Greeting
class component to a function:
import { Component } from 'react'; class Greeting extends Component { render() { return <h1>Hello, {this.props.name}!</h1>; } } export default function App() { return ( <> <Greeting name="Sara" /> <Greeting name="Cahal" /> <Greeting name="Edite" /> </> ); }
Define a function called Greeting
. This is where you will move the body of your render
function.
function Greeting() {
// ... move the code from the render method here ...
}
Instead of this.props.name
, define the name
prop using the destructuring syntax and read it directly:
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
Here is a complete example:
function Greeting({ name }) { return <h1>Hello, {name}!</h1>; } export default function App() { return ( <> <Greeting name="Sara" /> <Greeting name="Cahal" /> <Greeting name="Edite" /> </> ); }
Migrating a component with state from a class to a function
Suppose you’re converting this Counter
class component to a function:
import { Component } from 'react'; export default class Counter extends Component { state = { name: 'Taylor', age: 42, }; handleNameChange = (e) => { this.setState({ name: e.target.value }); } handleAgeChange = (e) => { this.setState({ age: this.state.age + 1 }); }; render() { return ( <> <input value={this.state.name} onChange={this.handleNameChange} /> <button onClick={this.handleAgeChange}> Increment age </button> <p>Hello, {this.state.name}. You are {this.state.age}.</p> </> ); } }
Start by declaring a function with the necessary state variables:
import { useState } from 'react';
function Counter() {
const [name, setName] = useState('Taylor');
const [age, setAge] = useState(42);
// ...
Next, convert the event handlers:
function Counter() {
const [name, setName] = useState('Taylor');
const [age, setAge] = useState(42);
function handleNameChange(e) {
setName(e.target.value);
}
function handleAgeChange() {
setAge(age + 1);
}
// ...
Finally, replace all references starting with this
with the variables and functions you defined in your component. For example, replace this.state.age
with age
, and replace this.handleNameChange
with handleNameChange
.
Here is a fully converted component:
import { useState } from 'react'; export default function Counter() { const [name, setName] = useState('Taylor'); const [age, setAge] = useState(42); function handleNameChange(e) { setName(e.target.value); } function handleAgeChange() { setAge(age + 1); } return ( <> <input value={name} onChange={handleNameChange} /> <button onClick={handleAgeChange}> Increment age </button> <p>Hello, {name}. You are {age}.</p> </> ) }
Migrating a component with lifecycle methods from a class to a function
Suppose you’re converting this ChatRoom
class component with lifecycle methods to a function:
import { Component } from 'react'; import { createConnection } from './chat.js'; export default class ChatRoom extends Component { state = { serverUrl: 'https://localhost:1234' }; componentDidMount() { this.setupConnection(); } componentDidUpdate(prevProps, prevState) { if ( this.props.roomId !== prevProps.roomId || this.state.serverUrl !== prevState.serverUrl ) { this.destroyConnection(); this.setupConnection(); } } componentWillUnmount() { this.destroyConnection(); } setupConnection() { this.connection = createConnection( this.state.serverUrl, this.props.roomId ); this.connection.connect(); } destroyConnection() { this.connection.disconnect(); this.connection = null; } render() { return ( <> <label> Server URL:{' '} <input value={this.state.serverUrl} onChange={e => { this.setState({ serverUrl: e.target.value }); }} /> </label> <h1>Welcome to the {this.props.roomId} room!</h1> </> ); } }
First, verify that your componentWillUnmount
does the opposite of componentDidMount
. In the above example, that’s true: it disconnects the connection that componentDidMount
sets up. If such logic is missing, add it first.
Next, verify that your componentDidUpdate
method handles changes to any props and state you’re using in componentDidMount
. In the above example, componentDidMount
calls setupConnection
which reads this.state.serverUrl
and this.props.roomId
. This is why componentDidUpdate
checks whether this.state.serverUrl
and this.props.roomId
have changed, and resets the connection if they did. If your componentDidUpdate
logic is missing or doesn’t handle changes to all relevant props and state, fix that first.
In the above example, the logic inside the lifecycle methods connects the component to a system outside of React (a chat server). To connect a component to an external system, describe this logic as a single Effect:
import { useState, useEffect } from 'react';
function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:1234');
useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => {
connection.disconnect();
};
}, [serverUrl, roomId]);
// ...
}
This useEffect
call is equivalent to the logic in the lifecycle methods above. If your lifecycle methods do multiple unrelated things, split them into multiple independent Effects. Here is a complete example you can play with:
import { useState, useEffect } from 'react'; import { createConnection } from './chat.js'; export default function ChatRoom({ roomId }) { const [serverUrl, setServerUrl] = useState('https://localhost:1234'); useEffect(() => { const connection = createConnection(serverUrl, roomId); connection.connect(); return () => { connection.disconnect(); }; }, [roomId, serverUrl]); return ( <> <label> Server URL:{' '} <input value={serverUrl} onChange={e => setServerUrl(e.target.value)} /> </label> <h1>Welcome to the {roomId} room!</h1> </> ); }
Migrating a component with context from a class to a function
In this example, the Panel
and Button
class components read context from this.context
:
import { createContext, Component } from 'react'; const ThemeContext = createContext(null); class Panel extends Component { static contextType = ThemeContext; render() { const theme = this.context; const className = 'panel-' + theme; return ( <section className={className}> <h1>{this.props.title}</h1> {this.props.children} </section> ); } } class Button extends Component { static contextType = ThemeContext; render() { const theme = this.context; const className = 'button-' + theme; return ( <button className={className}> {this.props.children} </button> ); } } function Form() { return ( <Panel title="Welcome"> <Button>Sign up</Button> <Button>Log in</Button> </Panel> ); } export default function MyApp() { return ( <ThemeContext.Provider value="dark"> <Form /> </ThemeContext.Provider> ) }
When you convert them to function components, replace this.context
with useContext
calls:
import { createContext, useContext } from 'react'; const ThemeContext = createContext(null); function Panel({ title, children }) { const theme = useContext(ThemeContext); const className = 'panel-' + theme; return ( <section className={className}> <h1>{title}</h1> {children} </section> ) } function Button({ children }) { const theme = useContext(ThemeContext); const className = 'button-' + theme; return ( <button className={className}> {children} </button> ); } function Form() { return ( <Panel title="Welcome"> <Button>Sign up</Button> <Button>Log in</Button> </Panel> ); } export default function MyApp() { return ( <ThemeContext.Provider value="dark"> <Form /> </ThemeContext.Provider> ) }