Bereaksi kuis kontes parsing dari booth HeadHunter di HolyJs 2018

Hai Pada 24-25 September, sebuah konferensi para pengembang front-end HolyJs berlangsung di Moskow https://holyjs-moscow.ru/ . Kami datang ke konferensi dengan stand kami di mana kami mengadakan kuis. Ada kuis utama - 4 babak kualifikasi dan 1 putaran final, di mana Apple Watch dan konstruktor lego dimainkan. Dan secara terpisah, kami melakukan kuis pengetahuan reaksi.


Di bawah tugas kuis mengurai cat pada reaksi. Opsi yang benar akan disembunyikan di bawah spoiler, jadi Anda tidak hanya dapat membaca analisisnya, tetapi juga memeriksa diri Anda sendiri :)


gambar


Ayo pergi!


Untuk kenyamanan, kami mengelompokkan pertanyaan menjadi beberapa bagian:


Bagian 1. Pemahaman dasar operasi this.setState dan memperbarui siklus hidup komponen:


Pertanyaan 1.


      react-: 1) SetProps, SetState, ForceUpdate 2) ForceUpdate, SetState 3) ForceUpdate, SetState, Parent (re)render 4) ForceUpdate, SetState, directly call UpdateComponent 

Jawabannya

3) ForceUpdate, SetState, Parent (re) render


Pertanyaan 2.


  ,   this.setState({})  react 1)   ,  updating lifecycle 2)   ,    3) React    "Object cannot be empty" 4)    state   

Jawabannya

1) Komponen ditandai kotor, memperbarui siklus hidup disebut


Analisis pertanyaan 1 dan 2

Untuk menjawab pertanyaan, kami akan menganalisis 2 bagian:
1) Permintaan komponen sendiri untuk memperbarui siklus
2) Permintaan di luar komponen


Komponen itu sendiri memiliki 2 cara untuk memperbarui sendiri:
1) this.setState dan this.forceUpdate. Dalam hal ini, komponen akan ditandai kotor dan pada centang Rekonsiliasi, jika prioritas untuk rendering, siklus pembaruan akan dimulai.


Fakta menarik: this.setState({}) dan this.forceUpdate berbeda. Ketika this.setState({}) dipanggil, loop pembaruan penuh disebut, tidak seperti this.forceUpdate , ketika loop pembaruan dimulai tanpa metode shouldComponentUpdate. Contoh karya this.setState({}) dapat ditemukan di sini: https://codesandbox.io/s/m5jz2701l9 (jika Anda mengganti setState dengan forceUpdate dalam contoh, Anda dapat melihat bagaimana perilaku komponen berubah).


2) Ketika orang tua komponen dirender kembali, ia mengembalikan bagian vDOM, semua anak-anak yang perlu diperbarui, dan mereka juga akan disebut siklus hidup pembaruan penuh. Penghitungan ulang lengkap dari subtree dapat dihindari dengan menjelaskan shouldComponentUpdate atau dengan mendefinisikan komponen sebagai PureComponent.


Pertanyaan 3


   Component  PureComponent (PC) 1) Component   ,    Pure 2) PC  SCU,  shallowEqual props  state 3) PC    ,    store 4)  PC    shouldComponentUpdate 

Jawab dan parsing

2) PC mengimplementasikan SCU, melakukan props dangkal dan menyatakan


Seperti yang kita bahas sebelumnya, ketika (kembali) merender induk, seluruh subtree akan dikirim ke siklus hidup yang diperbarui. Bayangkan Anda telah memperbarui elemen root. Dalam hal ini, sesuai dengan efek berantai, Anda harus memperbarui hampir seluruh pohon reaksi. Untuk mengoptimalkan dan tidak mengirim pembaruan yang tidak perlu, pada reaksi ada metode shouldComponentUpdate , yang memungkinkan Anda untuk mengembalikan true jika komponen harus diperbarui, dan false jika tidak. Untuk menyederhanakan perbandingan dalam reaksi, Anda dapat mewarisi dari PureComponent untuk bersiap-siap segera shouldComponentUpdate , yang membandingkan dengan referensi (jika menyangkut jenis objek) atau dengan nilai (jika ini tentang jenis nilai) semua alat peraga dan status yang masuk ke dalam komponen.


Pertanyaan 4.


 this.setState(() => {}, () => {}) —       setState? 1) set   .    updating 2)       state 3) setState   1  

Jawab dan parsing

2) Fungsi kedua akan dipanggil setelah memperbarui keadaan


Ada dua metode dalam React-lifecycle: componentDidMount untuk loop pemasangan dan componentDidUpdate untuk memperbarui, di mana Anda dapat menambahkan beberapa logika setelah memperbarui komponen. Misalnya, buat permintaan http, buat beberapa perubahan gaya, dapatkan metrik elemen html, dan (dengan syarat) buat setState. Jika Anda ingin mengambil tindakan setelah mengubah bidang tertentu dalam keadaan, maka dalam metode componentDidUpdate Anda harus menulis perbandingan:


 componentDidUpdate(prevProp, prevState) { if (prevState.foo !== this.state.foo) { // do awesome things here } } 

Atau Anda dapat melakukannya dengan setState:


 setState( // set new foo {foo: 'baz'}, () => { // do awesome things here } ); 

Setiap pendekatan memiliki pro dan kontra (misalnya, jika Anda mengubah setState di beberapa tempat, mungkin lebih mudah untuk menulis suatu kondisi satu kali).


Pertanyaan 5.


       render: class A extends React.PureComponent { render() { console.log('render'); return <div /> } } function Test() { return <A foo='bar' onClick={() => console.log('foo')} /> } const rootElement = document.getElementById("root"); ReactDOM.render(<Test />, rootElement); setTimeout(() => ReactDOM.render(<Test />, rootElement)); 1) 1 2) 2 3) 3 4) 0 

Jawabannya

2) 2


Pertanyaan 6.


       render: class A extends React.PureComponent { render() { console.log('render'); return <div /> } } function Test() { return <A foo='bar' /> } const rootElement = document.getElementById("root"); ReactDOM.render(<Test />, rootElement); setTimeout(() => ReactDOM.render(<Test />, rootElement)); 1) 1 2) 2 3) 3 4) 0 

Jawabannya

1) 1


Pertanyaan 7.


       render: class A extends React.PureComponent { componentDidMount() { console.log('render'); } render() { return <div /> } } const rootElement = document.getElementById("root"); ReactDOM.render(<A />, rootElement); setTimeout(() => ReactDOM.render(<A />, rootElement)); 1) 1 2) 2 3) 3 4) 0 

Jawabannya

1) 1


Analisis pertanyaan 5-7

Pertanyaan 5–7 Diperlukan untuk hal yang sama - untuk memeriksa pemahaman tentang pekerjaan PureComponent dan memperbarui komponen saat pemindahan alat peraga. Jika di dalam metode render kami meneruskan panggilan balik jsx, menjelaskan ini secara langsung dalam fungsi render:


 render () { return <Button onClick={() => {}} />; } 

Kemudian setiap render induk akan memperbarui handler klik yang diberikan. Ini terjadi karena setiap render membuat fungsi baru dengan tautan unik, yang bila dibandingkan di PureComponent akan menunjukkan bahwa alat peraga baru tidak sama dengan yang lama dan Anda perlu memperbarui komponen. Dalam kasus ketika semua pemeriksaan lulus dan shouldComponentUpdate mengembalikan false, pembaruan tidak terjadi.


Bagian 2. Kunci dalam Bereaksi


Analisis terperinci tentang kunci yang kami terbitkan di sini: https://habr.com/company/hh/blog/352150/


Pertanyaan 1.


     key,      ? 1)         key 2)    updating lifecycle 3)   key  4)    reconciliation 

Jawab dan parsing

1) Hapus instance sebelumnya dan pasang yang baru saat mengubah kunci


Tanpa menggunakan kunci, reaksi akan membandingkan daftar elemen berpasangan dari atas ke bawah. Jika kita menggunakan kunci, perbandingan akan terjadi pada kunci yang sesuai. Jika kunci baru telah muncul, maka komponen seperti itu tidak akan dibandingkan dengan siapa pun dan akan segera dibuat dari awal.
Anda dapat menggunakan metode ini bahkan jika kita memiliki 1 elemen: kita dapat mengatur <A key="1" /> , dalam render berikutnya kita tentukan <A key="2" /> dan dalam hal ini reaksi akan menghapus <A key="1" /> dan buat dari awal <A key="2" /> .


Pertanyaan 2.


       this.prop.key? 1)  2)  3)   static getKey 

Jawab dan parsing

2) Tidak


Komponen dapat mempelajari kunci dari anak-anaknya, yang diberikan padanya sebagai alat bantu, tetapi tidak dapat mempelajari tentang kunci tersebut.


Pertanyaan 3.


       render: class A extends React.PureComponent { componentDidMount() { console.log('render'); } render() { return <div /> } } const rootElement = document.getElementById("root"); ReactDOM.render(<A key='1' />, rootElement); setTimeout(() => ReactDOM.render(<A />, rootElement)); 1) 1 2) 2 3) 3 4) 0 

Jawab dan parsing

2) 2


Saat mengganti kunci, komponen akan dibuat ulang, sehingga render akan ditampilkan dua kali.


Bagian 3. Pertanyaan tentang jsx


Pertanyaan 1.


   .           1)    prop / context 2)        3)  setParentProps 4)  static getParentRef 

Jawab dan parsing

1) Callback dalam bentuk prop / konteks
2) Penghapusan lapisan model dan bekerja melaluinya


Ada dua jawaban yang benar. Memilih salah satu dari mereka pada kuis akan menghitung poin Anda. Pertanyaan ini untuk pengetahuan aliran data yang bereaksi. Data dari atas ke bawah didistribusikan dalam bentuk alat peraga atau konteks, dapat berisi panggilan balik, yang dapat dipanggil komponen di bawah ini untuk memengaruhi kondisi sistem.
Metode lain yang menggabungkan pemindahan model, konteks dan penyangga, adalah, misalnya, pengikatan re-redux.
Perpustakaan ini mengambil model yang berasal dari react (redux). Set redux.store di Provider, yang sebenarnya menetapkan store dalam konteks. Kemudian pengembang menggunakan koneksi HOC, yang masuk ke dalam konteks, berlangganan untuk menyimpan (store.subscribe) perubahan, dan ketika toko berubah, menceritakan fungsi mapStateToProps . Jika data telah berubah, itu menetapkan mereka dalam alat peraga ke objek yang dibungkus.
Pada saat yang sama, connect memungkinkan Anda untuk menentukan mapDispatchToProps , tempat pengembang menentukan actionCreator yang perlu diteruskan ke komponen. Kami, pada gilirannya, menerimanya dari luar (tanpa konteks), mengikat actionCreators ke toko (kami membungkusnya di store.dispatch) dan meneruskannya ke komponen yang dibungkus sebagai alat peraga.


Pertanyaan 2.


   props   jsx?     1)   2)   children 

Jawab dan parsing

1) Dalam


Anda dapat mentransfer ke siapa saja. Sebagai contoh:


 <Button icon={<Icon kind='warning'/>}></Button> 

Gambar tombol dengan ikon. Pendekatan ini sangat mudah digunakan untuk meninggalkan komponen hak untuk mengontrol lokasi berbagai elemen relatif satu sama lain, daripada memilah satu penyangga anak-anak.


Bagian 4. Advanced Memahami setState


Berikut adalah 3 pertanyaan yang sangat terkait:


Pertanyaan 1.


 this.state = {a: 'a'}; ... this.setState({a: 'b'}); this.setState({a: this.state.a + 1}) this.state? 1) {a: 'a1'} 2) {a: 'b1'} 3)   4) {a: 'a'} 

Jawabannya

3) Tidak cukup data


Pertanyaan 2.


 this.state={a: 'a'} ... this.setState({a: 'b'}) this.setState(state => ({a: state.a + 1})) this.state? 1) {a: 'a1'} 2) {a: 'b1'} 3)   4) {a: 'ab1'} 

Jawabannya

2) {a: 'b1'}


Pertanyaan 3.


    2 setState  componentDidUpdate  updating lifecycle   1) 1 2) 2 3) 3 4)   

Jawabannya

1) 1


Analisis pertanyaan 1-3

Semua pekerjaan setState dijelaskan sepenuhnya di sini:
1) https://reactjs.org/docs/react-component.html#setstate
2) https://stackoverflow.com/questions/48563650/does-react-keep-the-order-for-state-updates/48610973#48610973


Faktanya adalah setState tidak terjadi secara serempak.
Dan jika ada beberapa panggilan untuk setState berturut-turut, tergantung pada apakah kita berada di dalam metode siklus-reaksi, fungsi handler dari event-reaksi (onChange, onClick) atau tidak, pelaksanaan setState tergantung.
Di dalam handler reaksi, setState bekerja dalam batch (perubahan digulir hanya setelah fungsi yang ditentukan pengguna dalam tumpukan panggilan selesai dan kami masuk ke fungsi yang disebut event handler dan metode siklus hidup kami). Mereka berguling satu demi satu, jadi jika kita berada di dalam penangan reaksi, kita mendapatkan:


 this.state = {a: 'a'}; // a: 'a' ... this.state.a // a: 'a' this.setState({a: 'b'}); // a: 'b' +   .       this.state.a // a: 'a' this.setState({a: this.state.a + 1}) // a: 'a1' 

sejak perubahan terjadi batchevo.
Tetapi pada saat yang sama, jika setState dipanggil di luar penangan reaksi:


 this.state = {a: 'a'}; // a: 'a' ... this.state.a // a: 'a' this.setState({a: 'b'}); // a: 'b' +     this.state.a // a: 'b' this.setState({a: this.state.a + 1}) // a: 'b1' +     

Karena dalam kasus ini, perubahan akan digulirkan secara terpisah.


Bagian 5. Redux


Pertanyaan 1.


     action,  () => {} ? 1) .  action      type 2) ,   action      type 3) ,    middleware   action 4) ,       dispatch 

Jawab dan parsing

3) Ya, Anda perlu mendefinisikan middleware khusus untuk tindakan semacam itu


Ambil redux-thunk sebagai contoh paling sederhana. Semua middleware adalah blok kode kecil:
https://github.com/reduxjs/redux-thunk/blob/master/src/index.js#L2-L9


 return ({ dispatch, getState }) => next => action => { if (typeof action === 'function') { return action(dispatch, getState, extraArgument); } return next(action); }; 

Bagaimana cara kerja middleware?
Mereka mendapatkan kontrol sebelum aksi tiba di toko. Oleh karena itu, tindakan yang telah ditimpa akan terlebih dahulu melalui rantai middleware.
Setiap middleware menerima instance toko, metode selanjutnya, yang memungkinkan Anda untuk meneruskan tindakan lebih lanjut, dan tindakan itu sendiri.
Jika middleware memproses tindakan kustom, seperti redux-thunk, maka jika tindakan adalah fungsi, itu tidak meneruskan tindakan lebih lanjut, tetapi "menenggelamkan" itu, alih-alih memanggil tindakan dengan metode pengiriman dan getState yang diteruskan ke sana.
Apa yang akan terjadi jika redux-thunk melakukan tindakan selanjutnya, yang merupakan fungsi?
Sebelum memanggil reduksi, toko memeriksa jenis tindakan. Itu harus memenuhi ketentuan berikut:
1) Itu harus menjadi objek
2) Ini harus memiliki bidang tipe
3) Bidang jenis harus dari tipe string


Jika salah satu kondisi tidak terpenuhi, redux akan melempar kesalahan.


Pertanyaan bonus:


Pertanyaan Bonus 1.


   ? class Todos extends React.Component { getSnapshotBeforeUpdate(prevProps, prevState) { return this.props.list.length - prevProps.list.length; } componentDidUpdate(a, b, c) { console.log(c); } ... } ReactDOM.render(<Todos list={['a','b']} />, app); setTimeout(() => ReactDOM.render(<Todos list={['a','b','a','b']} />, app), 0); a) 0 b) 1 c) 2 d) undefined 

Jawab dan parsing

c) 2


getSnapshotBeforeUpdate adalah fungsi yang jarang digunakan dalam bereaksi yang memungkinkan Anda untuk mendapatkan snapshot, yang kemudian akan diteruskan ke componentDidUpdate. Metode ini diperlukan untuk melakukan pra-perhitungan data tertentu berdasarkan yang dapat Anda buat, misalnya, mengambil permintaan.


Pertanyaan Bonus 2.


        2,5 ? function Input() { const [text, setText] = useState("World!"); useEffect( () => { let id = setTimeout(() => { setText("Hello " + text); }, 1000); return () => { clearTimeout(id); }; }, [text] ); return ( <input value={text} onChange={e => { setText(e.target.value); }} /> ); } a) "World!" b) "Hello World!" c) "Hello Hello World!" d)    

Jawabannya

c) "Hello Hello World!"


Ini sudah menjadi pertanyaan untuk mengetahui fitur-fitur baru dalam reaksi, itu bukan dalam kuis kami. Mari kita coba di komentar untuk menjelaskan secara terperinci operasi kode dari pertanyaan terakhir :)

Source: https://habr.com/ru/post/id431492/


All Articles