क्यों आप JSX सहारा में इनलाइन तीर कार्यों का उपयोग नहीं करना चाहिए
जेएसएक्स में एरो फ़ंक्शंस या बाइंडिंग का उपयोग करना एक खराब अभ्यास है जो प्रदर्शन को नुकसान पहुंचाता है, क्योंकि प्रत्येक रेंडर पर फ़ंक्शन को फिर से बनाया जाता है।
जब भी कोई फ़ंक्शन बनाया जाता है, तो पिछला फ़ंक्शन कचरा एकत्र किया जाता है। कई तत्वों को प्रस्तुत करने से एनिमेशन में जान पैदा हो सकती है।
इनलाइन एरो फंक्शन का उपयोग करने से PureComponent
एस, और घटकों का उपयोग होता shallowCompare
है जो shouldComponentUpdate
किसी भी तरह रेंडर करने की विधि में उपयोग करते हैं । चूंकि हर बार एरो फंक्शन प्रॉप को फिर से बनाया जाता है, इसलिए उथला तुलना इसे प्रॉप में बदलाव के रूप में पहचानेगी, और घटक रेंडर करेगा।
जैसा कि आप निम्न 2 उदाहरणों में देख सकते हैं - जब हम इनलाइन एरो फंक्शन का उपयोग करते हैं, तो <Button>
घटक को हर बार रेंडर किया जाता है (कंसोल 'रेंडर बटन' टेक्स्ट दिखाता है)।
उदाहरण 1 - इनलाइन हैंडलर के बिना PureComponent
class Button extends React.PureComponent {
render() {
const { onClick } = this.props;
console.log('render button');
return (
<button onClick={ onClick }>Click</button>
);
}
}
class Parent extends React.Component {
state = {
counter: 0
}
onClick = () => this.setState((prevState) => ({
counter: prevState.counter + 1
}));
render() {
const { counter } = this.state;
return (
<div>
<Button onClick={ this.onClick } />
<div>{ counter }</div>
</div>
);
}
}
ReactDOM.render(
<Parent />,
document.getElementById('root')
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="root"></div>
उदाहरण 2 - इनलाइन हैंडलर के साथ PureComponent
class Button extends React.PureComponent {
render() {
const { onClick } = this.props;
console.log('render button');
return (
<button onClick={ onClick }>Click</button>
);
}
}
class Parent extends React.Component {
state = {
counter: 0
}
render() {
const { counter } = this.state;
return (
<div>
<Button onClick={ () => this.setState((prevState) => ({
counter: prevState.counter + 1
})) } />
<div>{ counter }</div>
</div>
);
}
}
ReactDOM.render(
<Parent />,
document.getElementById('root')
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<div id="root"></div>
this
बिना तीर के कार्यों को बांधने के तरीके
कंस्ट्रक्टर में मैन्युअल तरीके से बाइंडिंग:
class Button extends React.Component {
constructor(props, context) {
super(props, context);
this.cb = this.cb.bind(this);
}
cb() {
}
render() {
return (
<button onClick={ this.cb }>Click</button>
);
}
}
एक तीर फ़ंक्शन के साथ प्रस्ताव-वर्ग-फ़ील्ड का उपयोग करके एक विधि बांधना । जैसा कि यह एक चरण 3 का प्रस्ताव है, आपको स्टेज 3 प्रीसेट या क्लास प्रॉपर्टीज़ को अपने बैबल कॉन्फ़िगरेशन में बदलना होगा।
class Button extends React.Component {
cb = () => { // the class property is initialized with an arrow function that binds this to the class
}
render() {
return (
<button onClick={ this.cb }>Click</button>
);
}
}
आंतरिक कॉलबैक के साथ फ़ंक्शन घटक
जब हम किसी फंक्शन कंपोनेंट के अंदर एक इनर फंक्शन (उदाहरण के लिए ईवेंट हैंडलर) बनाते हैं, तो हर बार कंपोनेंट के रेंडर होने पर फंक्शन रीक्रिएट किया जाएगा। यदि फ़ंक्शन एक बच्चे घटक ( Button
इस मामले में ) के लिए सहारा (या संदर्भ के माध्यम से) के रूप में पारित किया जाता है , तो वह बच्चा फिर से भी प्रस्तुत करेगा।
उदाहरण 1 - आंतरिक कॉलबैक के साथ फ़ंक्शन घटक:
const { memo, useState } = React;
const Button = memo(({ onClick }) => console.log('render button') || (
<button onClick={onClick}>Click</button>
));
const Parent = () => {
const [counter, setCounter] = useState(0);
const increment = () => setCounter(counter => counter + 1); // the function is recreated all the time
return (
<div>
<Button onClick={increment} />
<div>{counter}</div>
</div>
);
}
ReactDOM.render(
<Parent />,
document.getElementById('root')
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
इस समस्या को हल करने के लिए, हम कॉलबैक को useCallback()
हुक के साथ लपेट सकते हैं , और निर्भरता को एक खाली सरणी पर सेट कर सकते हैं।
नोट:useState
उत्पन्न समारोह एक अपडेटर समारोह, कि वर्तमान स्थिति प्रदान करता है स्वीकार करता है। इस तरह, हमें वर्तमान स्थिति पर निर्भरता निर्धारित करने की आवश्यकता नहीं है useCallback
।
उदाहरण 2 - उपयोग के साथ लिपटे एक आंतरिक कॉलबैक के साथ फंक्शन घटक:
const { memo, useState, useCallback } = React;
const Button = memo(({ onClick }) => console.log('render button') || (
<button onClick={onClick}>Click</button>
));
const Parent = () => {
const [counter, setCounter] = useState(0);
const increment = useCallback(() => setCounter(counter => counter + 1), []);
return (
<div>
<Button onClick={increment} />
<div>{counter}</div>
</div>
);
}
ReactDOM.render(
<Parent />,
document.getElementById('root')
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>