Reactjs-də component-lərin iki dəfə render olması problemi və həlli.
--
Bu problemin baş verməsinin səbəbi React.StrictMode-un bir xüsusiyyətidir. Əslində bu sadəcə development mode-da baş verir və əsas məqsədi isə render mərhələsində baş verə biləcək yan təsirlərin qarşısının alınmasıdır.
Fərqli misallar üzərində bunu müşahidə etmək mümkündür.
A) useState ilə yazılmış functional component-ə nəzər salaq.
function App() {
const [click, setClick] = React.useState(0);console.log('Render edildi ', click);
return (
<div>
<button onClick={() => setClick(click => click + 1)}>
Clicks: {click}
</button>
</div>
)
}
Əgər create-react-app istifadə edərək react app yaratsaq və npm start ilə çalışdırsaq browser console-da aşağıdakı output-la qarşılaşacağıq.
Render edildi 0
Render edildi 0
Əgər button-a bir dəfə click-ləsək belə bir output-la qarşılaşacağıq.
Render edildi 1
Render edildi 1
Bunun səbəbi index.js faylındakı React.StrictMode köməkçi tool-dur.
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
<React.StrictMode>
-u silsək problemin həll olacaq və npm start --port 3001
ilə yeni port üzərindən çalışdırsaq browser console-da belə bir output-la qarşılaşacağıq.
Render edildi 0
Render edildi 1
B) useState əvəzinə useReduce istifadə edək.
useState
yerinə useReduce
işlətdim və nəticə dəyişmədi:
function App() {
const [clicks, dispatch] = React.useReducer((state, action) => {
switch (action.type) {
case 'click':
return state + 1;
default:
throw new Error()
}
}, 0)console.log('Render edildi ', clicks);
return (
<div >
<button onClick={()=>dispatch({type:'click'})}>
Clicks: {clicks}
</button>
</div>
)
}
Browser console:
Render edildi 0
Render edildi 0Render edildi 1
Render edildi 1
C) Class Component
Functional Component əvəzinə Class Component istifadə etdikdə də eyni problemlə qarşılaşdığımızı görürük.
class App extends React.Component {
render() {
console.log('Render edildi');
return null;
}
}
Browser console:
Render edildi
Bəs burada nə baş verir ki biz bu problemlə qarşılaşırıq?
Əsas səbəb 16.3.0 versiyası ilə birlikdə təqdim edilən React.StrictMode
-dur. Bu versiyadan əvvəl köməkçi tool sadəcə class component-lər üçün istifadə edilə bilirdi. 16.8.0 versiyasının gəlişi ilə bu tool hooks üçün də istifadə edilə bilən hala gəldi.
Applikasiyada potensial problemləri vurğulayan alətlərdən biri
StrictMode
-dur.StrictMode
,Fragment
kimi heç bir görünən UI render etmir. Bu alət sadəcə descendants üçün əlavə yoxlamalar edərək xəbərdarlıqlar göstərir. ‒ rəsmi React sənədi
StrictMode
aşağıdakı problemlər üçün faydalıdır:
- Təhlükəli lifecycle işlədən komponentlərin tapılması
- Köhnə mətn ref API-ının istifadə edilməsi haqqında xəbərdarlıq
- Köhnə findDOMNode-un istifadə edilməsi haqqında xəbərdarlıq
- Gözlənilməz side effektlərin tapılması
- Köhnə kontekst API-larının tapılması
Strict rejim avtomatik olaraq belə yan effektləri aşkar edə bilmir. Amma, bu rejim ilə yan effektlərin olduğu yerləri tapmaq mümkündür. Bu yan effektlərin tapılması üçün aşağıdakı funksiyalar iki dəfə çağrılır:
- Sinif komponentinin
constructor
,render
vəshouldComponentUpdate
funksiyaları - Sinif komponentinin statik
getDerivedStateFromProps
metodu - Funksiya komponentinin gövdələri
- State yeniləyici funksiyalar (
setState
funksiyasının ilk arqumenti) useState
,useMemo
vəuseReducer
-ə göndərilən funksiyalar
Niyə React.StrictMode istifadə edilməlidir?
React qısa müddət sonra Concurrent Mode adlı eksperimenti təqdim edəcək. Bu eksperiment, React applikasiyalarına responsive qalmağa, istifadəçinin cihaz imkanlarına və şəbəkə sürətinə düzgün cavab verməyə kömək edən yeni xüsusiyyətlər toplusudur.