આધુનિક વેબસાઇટ્સ વધુ ભવ્ય વિઝ્યુઅલ્સ સાથે ધ્યાન ખેંચવા માટે સ્પર્ધા કરે છે. Parallax heroes વ્યૂપોર્ટમાં ઊંડે સુધી વિસ્તરે છે. Carousels અનંતકાળ સુધી સ્ક્રોલ થાય છે. સાઇનઅપ ફોર્મ્સની પાછળ બેકગ્રાઉન્ડ વીડિયો ઓટો-પ્લે થાય છે. ડિઝાઇન પોર્ટફોલિયોમાં આ પેટર્ન પોલીશ્ડ અને આકર્ષક લાગે છે. પરંતુ તમારા પ્રેક્ષકોના એક ભાગ માટે, તે શારીરિક ટ્રિગર (physical trigger) સમાન છે.

વેસ્ટિબ્યુલર ડિસઓર્ડર (vestibular disorders) સાથે જીવતા લોકોને સતત ગતિ ધરાવતા મોટા વિસ્તારોનો સામનો કરવો પડે ત્યારે ઉબકા, ચક્કર અથવા માઈગ્રેનનો અનુભવ થાય છે. તેમને સુરક્ષિત રાખવા માટે, દરેક મુખ્ય ઓપરેટિંગ સિસ્ટમમાં હવે "Reduce Motion" એક્સેસિબિલિટી સેટિંગ શામેલ છે. વેબ બ્રાઉઝર્સ prefers-reduced-motion મીડિયા ક્વેરી દ્વારા તે પસંદગીને પ્રદર્શિત કરે છે. React ડેવલપર્સ જેઓ તેને ચોકસાઈથી અમલમાં મૂકવા માંગે છે, તેઓ @reactuses/core માંથી useReducedMotion હૂકનો ઉપયોગ કરી શકે છે. તે OS ની પસંદગીને boolean માં વાંચે છે, જો વપરાશકર્તા પોતાની પસંદગી બદલે તો તેને લાઈવ અપડેટ કરે છે, અને સર્વર-સાઇડ રેન્ડરિંગને ક્રેશ થયા વગર હેન્ડલ કરે છે.

શા માટે હાથથી બનાવેલા (Handmade) સોલ્યુશન્સ નિષ્ફળ જાય છે

તમે window.matchMedia('(prefers-reduced-motion: reduce)') દ્વારા જાતે જ આ પસંદગી વિશે ક્વેરી કરી શકો છો. ઘણા ડેવલપર્સ આવું કરે છે, અને તેના કારણે ઘણીવાર સૂક્ષ્મ બગ્સ (subtle bugs) સર્જાય છે.

પ્રથમ, તમે સરળતાથી 'change listener' ભૂલી શકો છો. જ્યારે કમ્પોનન્ટ માઉન્ટ થાય ત્યારે પ્રારંભિક ક્વેરી એકવાર ચાલે છે. જો કોઈ વપરાશકર્તા તમારી એપ ખોલે અને પછી સિસ્ટમ સેટિંગ્સમાં 'Reduce Motion' ને ટોગલ કરે (કારણ કે કેરોયુઝલ તેમને બીમાર કરી રહ્યું છે), તો તમારો કમ્પોનન્ટ તે અપડેટ વિશે ક્યારેય જાણી શકશે નહીં. મીડિયા ક્વેરી ઓબ્જેક્ટ addEventListener ને સપોર્ટ કરે છે, પરંતુ તેને યોગ્ય રીતે વાયર કરવું, અનમાઉન્ટ (unmount) વખતે તેને દૂર કરવું અને જૂના addListener સિન્ટેક્સને પોલીફિલ (polyfill) કરવું એ એવું બોઈલરપ્લેટ (boilerplate) છે જે કોપી-પેસ્ટ ભૂલોને આમંત્રણ આપે છે.

બીજું, SSR દરમિયાન window અસ્તિત્વ ધરાવતું નથી. જો તમારી એપ સર્વર પર રેન્ડર થાય છે, તો એક સાધારણ matchMedia કોલ રેફરન્સ એરર (reference error) ફેંકે છે અને રેન્ડરિંગને અટકાવી દે છે. પરિણામે તમારે ચેકને typeof window !== 'undefined' ગાર્ડ્સમાં લપેટવું પડે છે, ડિફોલ્ટનું અનુમાન લગાવવું પડે છે, અને આશા રાખવી પડે છે કે ક્લાયન્ટ હાઇડ્રેશન (client hydrate) સાથે તે મેચ થાય.

ત્રીજું, દરેક એનિમેટેડ કમ્પોનન્ટમાં તે જ લોજિકનું પુનરાવર્તન કરવું એ મેન્ટેનન્સ ડેબ્ટ (maintenance debt) બની જાય છે. એક ટીમમેટ લિસનરને એક રીતે લખે છે, બીજો તેને સંપૂર્ણપણે છોડી દે છે, અને ત્રીજો મોશનને પ્રાધાન્ય આપતું ડિફોલ્ટ હાર્ડ-કોડ કરે છે. એક હૂક આ અરાજકતાને કેન્દ્રિત કરે છે.

useReducedMotion આ ત્રણેય સમસ્યાઓનું સમાધાન કરે છે. તે એક સાદું boolean રિટર્ન કરે છે. તે સર્વર પર સુરક્ષિત રીતે 'no-op' કરે છે. તે લિસનરને આપમેળે એટેચ કરે છે અને ક્લીનઅપ કરે છે.

તેને અમલમાં મૂકવાની ત્રણ રીતો

એકવાર તમારી પાસે boolean આવી જાય પછી, તેના પર કાર્ય કરવા માટે તમારે એક વ્યૂહરચનાની જરૂર છે. અહીં ત્રણ પેટર્ન છે જે એક સિંગલ કમ્પોનન્ટથી લઈને આખી એપ્લિકેશન સુધી સ્કેલ કરી શકાય છે.

1. બિનજરૂરી કામ ટાળવા માટે CSS ક્લાસને ગેટ (Gate) કરો

સૌથી સીધો અભિગમ એ છે કે ભારે JavaScript એનિમેશન લૂપ્સને ક્યારેય શરૂ થતા અટકાવવા. કલ્પના કરો કે તમારી પાસે એક parallax ઇમેજ કમ્પોનન્ટ છે જે સામાન્ય રીતે સ્ક્રોલ ઇવેન્ટ્સને સાંભળે છે અને requestAnimationFrame લૂપની અંદર લેયર્સને ટ્રાન્સલેટ કરે છે. તે લોજિક ચલાવીને પછી વિઝ્યુઅલ રિઝલ્ટને દબાવવાને બદલે, પહેલા useReducedMotion ચેક કરો.

જો હૂક true રિટર્ન કરે, તો કમ્પોનન્ટને સ્ટેટિક વેરિઅન્ટ ક્લાસ સાથે રેન્ડર કરો અને useEffect ને સ્કીપ કરો જે સ્ક્રોલ લિસનર્સને બાંધે છે. બ્રાઉઝર ઓછું કામ કરશે. મોશન સેન્સિટિવિટી ધરાવતા વપરાશકર્તાઓ સ્થિર (fixed) ઇમેજ જોશે. બાકીના દરેકને ચાલતા લેયર્સ જોવા મળશે. કારણ કે એનિમેશન કોડ ક્યારેય ઇનિશિયલાઇઝ થતો નથી, તેથી તમે CPU અને બેટરી બંને બચાવી શકો છો.

2. તેને સીધું એનિમેશન લાઇબ્રેરીઓમાં ફીડ કરો

જો તમે Framer Motion જેવી લાઇબ્રેરીનો ઉપયોગ કરો છો, તો આ હૂક તમારા પ્રોપ ડેફિનેશનમાં સીધું જ જોડાઈ જાય છે. મોશન કમ્પોનન્ટ્સ વેરિઅન્ટ્સ, ટ્રાન્ઝિશન અને જેસ્ચર માટે કોન્ફિગરેશન ઓબ્જેક્ટ્સ સ્વીકારે છે. તમે ટ્રાન્ઝિશન પર કન્ડિશનલ રીતે duration: 0 સેટ કરવા માટે useReducedMotion માંથી મળતા boolean નો ઉપયોગ કરી શકો છો, અથવા