नमस्कार। 24-25 सितंबर को, मॉस्को में होलीजेज फ्रंट-एंड डेवलपर्स https://holyjs-moscow.ru/ का एक सम्मेलन आयोजित किया गया था। हम अपने स्टैंड के साथ सम्मेलन में आए, जिस पर हमने प्रश्नोत्तरी रखी। एक मुख्य प्रश्नोत्तरी थी - 4 क्वालीफाइंग राउंड और 1 फाइनल राउंड, जिस पर Apple वॉच और लेगो कंस्ट्रक्टर खेले गए थे। और अलग से, हमने एक प्रतिक्रिया ज्ञान प्रश्नोत्तरी का आयोजन किया।
कैट के तहत - प्रतिक्रिया पर क्विज़ कार्यों को पार्स करना। स्पॉइलर के नीचे सही विकल्प छिपा होगा, इसलिए आप न केवल विश्लेषण पढ़ सकते हैं, बल्कि खुद को भी देख सकते हैं :)

चलो चलते हैं!
सुविधा के लिए, हमने प्रश्नों को वर्गों में बांटा:
खंड 1. इस के संचालन की बुनियादी समझ। शुरू और घटक जीवनचक्र को अद्यतन करना:
प्रश्न 1।
react-: 1) SetProps, SetState, ForceUpdate 2) ForceUpdate, SetState 3) ForceUpdate, SetState, Parent (re)render 4) ForceUpdate, SetState, directly call UpdateComponent
जवाब है3) ForceUpdate, SetState, Parent (re) रेंडर
प्रश्न २।
, this.setState({}) react 1) , updating lifecycle 2) , 3) React "Object cannot be empty" 4) state
जवाब है1) घटक को गंदे के रूप में चिह्नित किया जाता है, अद्यतन जीवन चक्र को कहा जाता है
प्रश्न 1 और 2 का विश्लेषणप्रश्न का उत्तर देने के लिए, हम 2 भागों का विश्लेषण करेंगे:
1) चक्र को अपडेट करने के लिए स्वयं का घटक अनुरोध
2) घटक के बाहर अनुरोध
घटक के पास स्वयं को अपडेट करने के 2 तरीके हैं:
1) this.setState और this.forceUpdate इस मामले में, घटक को गंदे और टिक रीकॉन्सिलिलेशन पर चिह्नित किया जाएगा, अगर यह प्रतिपादन के लिए प्राथमिकता में है, तो एक अद्यतन चक्र शुरू होगा।
दिलचस्प तथ्य: this.setState({})
और this.forceUpdate
भिन्न हैं। जब this.setState({})
को कॉल किया जाता है, तो फुल this.setState({})
लूप कहा जाता है, इसके विपरीत this.forceUpdate
, जब अपडेटिंग लूप बिना कम्प्लॉन्सकंटपेंट विधि के प्रारंभ होता है। इस। this.setState({})
के कार्य का एक उदाहरण यहां पाया जा सकता है: https://codesandbox.io/s/m5jz2701l9 (यदि आप setState को बल के साथ प्रतिस्थापित करते हैं उदाहरण में, आप देख सकते हैं कि घटकों का व्यवहार कैसे बदलता है)।
2) जब घटक के माता-पिता को फिर से प्रस्तुत किया जाता है, तो यह vDOM भाग को वापस कर देता है, सभी बच्चों को जिन्हें अद्यतन करने की आवश्यकता होगी, और उन्हें पूर्ण अद्यतन जीवनचक्र भी कहा जाएगा। सबट्री के एक पूर्ण पाठ को ,ComComententUpdate का वर्णन करके या घटक को PureComponent के रूप में परिभाषित करके टाला जा सकता है।
प्रश्न 3
Component PureComponent (PC) 1) Component , Pure 2) PC SCU, shallowEqual props state 3) PC , store 4) PC shouldComponentUpdate
उत्तर और पार्सिंग2) पीसी एससीयू को लागू करता है, उथले प्रॉपल और राज्य का संचालन करता है
जैसा कि हमने पहले चर्चा की थी, जब (फिर से) माता-पिता को प्रदान करते हुए, संपूर्ण उपप्रकार को अद्यतन जीवन चक्र में भेजा जाएगा। कल्पना कीजिए कि आपने रूट एलिमेंट को अपडेट किया है। इस मामले में, श्रृंखला प्रभाव के अनुसार, आपको लगभग संपूर्ण प्रतिक्रिया-वृक्ष को अपडेट करना होगा। अनावश्यक अद्यतनों को ऑप्टिमाइज़ और न भेजने के लिए, प्रतिक्रिया में एक विधि चाहिए shouldComponentUpdate
, जो आपको सही वापस करने की अनुमति देती है यदि घटक को अपडेट किया जाना चाहिए, और अन्यथा गलत। प्रतिक्रिया में तुलना को सरल बनाने के लिए, आप PureComponent
से PureComponent
करने के लिए तुरंत तैयार हो सकते हैं shouldComponentUpdate
, जो संदर्भ से तुलना करता है (यदि यह ऑब्जेक्ट प्रकारों की बात आती है) या वैल्यू (यदि यह वैल्यू टाइप्स के बारे में है) तो सभी प्रॉप्स और स्टेट जो कंपोनेंट में आते हैं।
प्रश्न 4।
this.setState(() => {}, () => {}) — setState? 1) set . updating 2) state 3) setState 1
उत्तर और पार्सिंग2) राज्य को अपडेट करने के बाद दूसरा फ़ंक्शन कहा जाएगा
रिएक्ट-जीवनचक्र में दो विधियां हैं: अपडेटिंग के लिए बढ़ते लूप और कंपोनेंटड्यूपडेट के लिए कंपोनेंटडिमाउंट, जहां आप कंपोनेंट को अपडेट करने के बाद कुछ लॉजिक जोड़ सकते हैं। उदाहरण के लिए, http अनुरोध करें, कुछ शैली परिवर्तन करें, HTML तत्वों के मेट्रिक्स प्राप्त करें और (शर्त के अनुसार) सेटस्टेट करें। यदि आप राज्य में कुछ क्षेत्रों को बदलने के बाद कुछ कार्रवाई करना चाहते हैं, तो componentDidUpdate
विधि में आपको या तो तुलना लिखनी होगी:
componentDidUpdate(prevProp, prevState) { if (prevState.foo !== this.state.foo) { // do awesome things here } }
या आप इसे setState द्वारा कर सकते हैं:
setState( // set new foo {foo: 'baz'}, () => { // do awesome things here } );
प्रत्येक दृष्टिकोण में पेशेवरों और विपक्ष हैं (उदाहरण के लिए, यदि आप कई स्थानों पर सेटस्टेट बदलते हैं, तो एक बार एक शर्त लिखना अधिक सुविधाजनक हो सकता है)।
प्रश्न 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
प्रश्न 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
प्रश्न 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
प्रश्नों का विश्लेषण 5-7प्रश्न 5-7 एक ही चीज़ के लिए आवश्यक हैं - PureComponent
के काम की PureComponent
और प्रॉप्स के हस्तांतरण पर घटकों को अपडेट करने के लिए। यदि रेंडर विधि के अंदर हम एक jsx कॉलबैक में पास करते हैं, तो रेंडर फ़ंक्शन में सीधे इसका वर्णन करते हुए:
render () { return <Button onClick={() => {}} />; }
तब माता-पिता का प्रत्येक रेंडर दिए गए क्लिक हैंडलर को अपडेट करेगा। ऐसा इसलिए होता है क्योंकि हर रेंडर एक अनूठे लिंक के साथ एक नया फंक्शन बनाता है, जिसकी तुलना में PureComponent में दिखाई देगा कि नए प्रॉप्स पुराने के बराबर नहीं हैं और आपको कंपोनेंट को अपडेट करने की जरूरत है। उस स्थिति में जब सभी चेक पास हो जाते हैं और shouldComponentUpdate गलत हो जाता है, तो अपडेट नहीं होता है।
धारा 2. अभिक्रिया में कीज़
हमने यहां प्रकाशित कीज का विस्तृत विश्लेषण: https://habr.com/company/hh/blog/352150/
प्रश्न 1।
key, ? 1) key 2) updating lifecycle 3) key 4) reconciliation
उत्तर और पार्सिंग1) पिछले उदाहरण को हटाएं और कुंजी बदलते समय नए को माउंट करें
कुंजी का उपयोग किए बिना, प्रतिक्रिया शीर्ष से नीचे तक जोड़े में तत्वों की सूची की तुलना करेगी। यदि हम कुंजी का उपयोग करते हैं, तो तुलना संबंधित कुंजी पर होगी। यदि एक नई कुंजी दिखाई दी है, तो इस तरह के एक घटक की तुलना किसी के साथ नहीं की जाएगी और खरोंच से तुरंत बनाई जाएगी।
यदि हमारे पास 1 तत्व है तो भी आप इस विधि का उपयोग कर सकते हैं: हम <A key="1" />
सेट कर सकते हैं, अगले रेंडर में हम <A key="2" />
निर्दिष्ट करते हैं और इस मामले में प्रतिक्रिया <A key="1" />
हटा देगा। <A key="1" />
और खरोंच से बनाएं <A key="2" />
।
प्रश्न २।
this.prop.key? 1) 2) 3) static getKey
उत्तर और पार्सिंग2) नहीं
घटक अपने बच्चों से कुंजी सीख सकता है, जो इसे एक प्रस्ताव के रूप में पारित किया गया था, लेकिन इसकी कुंजी के बारे में नहीं सीख सकता है।
प्रश्न 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
उत्तर और पार्सिंग२) २
कुंजी बदलते समय, घटक को फिर से बनाया जाएगा, इसलिए रेंडर दो बार प्रदर्शित किया जाएगा।
खंड 3. jsx पर प्रश्न
प्रश्न 1।
. 1) prop / context 2) 3) setParentProps 4) static getParentRef
उत्तर और पार्सिंग1) प्रोप / संदर्भ के रूप में कॉलबैक
2) मॉडल की परत को हटाने और इसके माध्यम से काम करना
दो सही उत्तर हैं। उनमें से किसी को क्विज़ पर चुनना आपको अंक देगा। यह सवाल डेटा-फ्लो प्रतिक्रिया के ज्ञान के लिए है। ऊपर से नीचे तक डेटा को प्रॉपर या संदर्भ के रूप में वितरित किया जाता है, इसमें कॉलबैक हो सकता है, जिसे नीचे दिया गया घटक सिस्टम की स्थिति को प्रभावित करने के लिए कॉल कर सकता है।
मॉडल हटाने, संदर्भ और प्रोप के संयोजन का एक और तरीका है, उदाहरण के लिए, प्रतिक्रिया-रिडक्स बाइंडिंग।
यह पुस्तकालय प्रतिक्रिया (रेडक्स) से प्राप्त एक मॉडल लेता है। प्रदाता में redux.store सेट करता है, जो वास्तव में संदर्भ में स्टोर सेट करता है। तब डेवलपर HOC कनेक्ट का उपयोग करता है, जो संदर्भ में जाता है, स्टोर (store.subscribe) परिवर्तनों को सब्सक्राइब करता है, और जब स्टोर बदलता है, तो mapStateToProps
फ़ंक्शन को mapStateToProps
करता है। यदि डेटा बदल गया है, तो यह उन्हें लपेटे हुए ऑब्जेक्ट में प्रॉपर सेट करता है।
उसी समय, कनेक्ट आपको mapDispatchToProps
को निर्दिष्ट करने की अनुमति देता है, जहां डेवलपर उन एक्शन क्रिटर्स को निर्दिष्ट करता है जिन्हें घटक को पारित किया जाना चाहिए। हम, बदले में, उन्हें बाहर से (संदर्भ के बिना) प्राप्त करते हैं, actionCreators
को स्टोर में बाँधते हैं (उन्हें स्टोर में लपेटते हैं। सटीक) और उन्हें लिपटे घटक के लिए सहारा के रूप में पास करते हैं।
प्रश्न २।
props jsx? 1) 2) children
उत्तर और पार्सिंग1) किसी में
आप किसी को भी ट्रांसफर कर सकते हैं। उदाहरण के लिए:
<Button icon={<Icon kind='warning'/>}></Button>
एक आइकन के साथ एक बटन खींचता है। यह दृष्टिकोण एक बच्चे के प्रोप को छांटने के बजाय एक दूसरे के सापेक्ष विभिन्न तत्वों के स्थान को नियंत्रित करने के लिए घटक को छोड़ने के लिए उपयोग करने के लिए बहुत सुविधाजनक है।
अनुभाग 4. उन्नत समझ setState
यहाँ 3 दृढ़ता से संबंधित प्रश्न हैं:
प्रश्न 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'}
प्रश्न २।
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'}
प्रश्न 3।
2 setState componentDidUpdate updating lifecycle 1) 1 2) 2 3) 3 4)
प्रश्नों का विश्लेषण 1-3सेटस्टेट के सभी काम पूरी तरह से यहाँ वर्णित हैं:
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
तथ्य यह है कि सेटस्ट्रेट समकालिक रूप से नहीं होता है।
और अगर हम एक पंक्ति में सेटस्टैट करने के लिए कई कॉल करते हैं, तो इस पर निर्भर करता है कि हम प्रतिक्रिया-जीवनचक्र विधि के अंदर हैं, प्रतिक्रिया-घटना के हैंडलर फ़ंक्शन (onChange, onClick) या नहीं, setState का निष्पादन निर्भर करता है।
प्रतिक्रिया करने वाले हैंडलर के अंदर, बैचों में सेटस्टेट कार्य (कॉल स्टैक में उपयोगकर्ता द्वारा परिभाषित कार्यों के समाप्त होने के बाद ही बदलाव किए जाते हैं और हम उन कार्यों में शामिल हो जाते हैं, जो हमारे ईवेंट हैंडलर और जीवनचक्र विधियों को कहते हैं)। वे एक के बाद एक रोल करते हैं, इसलिए यदि हम रिएक्टर-हैंडलर के अंदर हैं, तो हम प्राप्त करते हैं:
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'
चूंकि बैटचेवो में बदलाव हुए थे।
लेकिन एक ही समय में, अगर setState को प्रतिक्रिया-संचालकों के बाहर बुलाया गया था:
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' +
चूंकि इस मामले में, परिवर्तन अलग से किए जाएंगे।
खंड 5. Redux
प्रश्न 1।
action, () => {} ? 1) . action type 2) , action type 3) , middleware action 4) , dispatch
उत्तर और पार्सिंग3) हां, आपको ऐसी कार्रवाई के लिए कस्टम मिडलवेयर को परिभाषित करने की आवश्यकता है
Redux-Thunk को सबसे सरल उदाहरण के रूप में लें। सभी मिडलवेयर कोड का एक छोटा ब्लॉक है:
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); };
मिडलवेयर कैसे काम करते हैं?
स्टोर पर कार्रवाई आने से पहले उन्हें नियंत्रण मिल जाता है। इसलिए, एक कार्रवाई जो अधिलेखित हो गई है, वह पहले मिडलवेयर श्रृंखला के माध्यम से जाएगी।
प्रत्येक मिडलवेयर एक स्टोर इंस्टेंस को स्वीकार करता है, अगली विधि, जो आपको आगे और आगे की कार्रवाई करने की अनुमति देती है।
यदि मिडलवेयर कस्टम क्रियाओं को संसाधित करता है, जैसे कि रिडक्स-थंक, तो यदि क्रिया एक फ़ंक्शन है, तो यह आगे कार्रवाई को आगे नहीं बढ़ाता है, लेकिन इसे प्रेषण के बजाय कार्रवाई को बुलाता है और गेटस्टैट तरीके से पारित कर देता है।
यदि एक्शन के लिए रेडक्स-थंक ने आगे किया, तो क्या होगा?
रिड्यूसर को कॉल करने से पहले, स्टोर प्रकार की कार्रवाई की जांच करता है। इसे निम्नलिखित शर्तों को पूरा करना चाहिए:
1) यह एक वस्तु होना चाहिए
2) इसका एक प्रकार का क्षेत्र होना चाहिए
3) टाइप फ़ील्ड स्ट्रिंग का प्रकार होना चाहिए
यदि शर्तों में से एक संतुष्ट नहीं है, तो Redux एक त्रुटि फेंक देगा।
बोनस प्रश्न:
बोनस प्रश्न 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
उत्तर और पार्सिंगग) २
getSnapshotBeforeUpdate
प्रतिक्रिया में एक शायद ही कभी इस्तेमाल किया जाने वाला फ़ंक्शन है जो आपको एक स्नैपशॉट प्राप्त करने की अनुमति देता है, जिसे तब कंपोनेंटड्यूपडेट को पास किया जाएगा। इस पद्धति के लिए कुछ आंकड़ों की पूर्व-गणना करने की आवश्यकता होती है, जिसके आधार पर आप तब कर सकते हैं, उदाहरण के लिए, एक अनुरोध।
बोनस प्रश्न 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)
यह पहले से ही प्रतिक्रिया में नई सुविधाओं को जानने का सवाल है, यह हमारे क्विज़ में नहीं था। चलो आखिरी सवाल से कोड के संचालन के बारे में विस्तार से वर्णन करने के लिए टिप्पणियों में प्रयास करें :)