நவீன இணையதளங்கள் பிரம்மாண்டமான காட்சிகளால் கவனத்தை ஈர்க்கப் போட்டியிடுகின்றன. Parallax hero பகுதிகள் வியூபோர்ட்டிற்குள் (viewport) ஆழமாக நீள்கின்றன. Carousels முடிவில்லாமல் நகர்கின்றன. Sign-up படிவங்களுக்குப் பின்னால் பின்னணி வீடியோக்கள் தானாகவே இயங்குகின்றன. ஒரு வடிவமைப்பு போர்ட்ஃபோலியோவில் (design portfolio) இவை நேர்த்தியானதாகவும் ஈர்க்கக்கூடியதாகவும் தோன்றலாம். ஆனால், உங்கள் பார்வையாளர்களில் ஒரு பகுதியினருக்கு, இவை உடல் ரீதியான பாதிப்புகளை ஏற்படுத்தும் தூண்டிகளாக அமைகின்றன.
வெஸ்டிபுலர் கோளாறுகள் (vestibular disorders) உள்ளவர்கள், தொடர்ச்சியான இயக்கங்கள் நிறைந்த பெரிய பகுதிகளைப் பார்க்கும்போது குமட்டல், தலைச்சுற்றல் அல்லது ஒற்றைத் தலைவலி போன்றவற்றை அனுபவிக்கிறார்கள். அவர்களைப் பாதுகாக்க, தற்போதுள்ள ஒவ்வொரு முக்கிய இயங்குதளமும் (operating system) "Reduce Motion" என்ற அணுகல்தன்மை (accessibility) அமைப்பைக் கொண்டுள்ளது. இணைய உலாவிகள் (Web browsers) அந்தத் தேர்வை prefers-reduced-motion media query மூலம் வெளிப்படுத்துகின்றன. இதைச் சரியாகப் பயன்படுத்த விரும்பும் React டெவலப்பர்கள், @reactuses/core-லிருந்து useReducedMotion hook-ஐப் பயன்படுத்தலாம். இது OS தேர்வை ஒரு boolean ஆகப் படிக்கிறது, பயனர் தனது முடிவை மாற்றினால் உடனுக்குடன் புதுப்பிக்கிறது, மேலும் server-side rendering-ஐத் தடையின்றி கையாள்கிறது.
ஏன் கைமுறைத் தீர்வுகள் தோல்வியடைகின்றன
நீங்கள் window.matchMedia('(prefers-reduced-motion: reduce)') மூலம் அந்தத் தேர்வை நீங்களே சரிபார்க்கலாம். பல டெவலப்பர்கள் அவ்வாறே செய்கிறார்கள், ஆனால் அது பல நுணுக்கமான பிழைகளுக்கு (bugs) வழிவகுக்கிறது.
முதலாவதாக, மாற்றங்களைக் கண்காணிக்கும் listener-ஐ நீங்கள் எளிதில் மறந்துவிடலாம். ஒரு component mount ஆகும்போது ஆரம்பக் கேள்வி (initial query) ஒருமுறை மட்டுமே இயங்கும். ஒரு பயனர் உங்கள் செயலியைத் திறந்து, ஒரு carousel அவர்களுக்கு உடல்நலக் குறைவை ஏற்படுத்துவதால், system settings-இல் Reduce Motion அமைப்பை மாற்றினால், உங்கள் component அந்த மாற்றத்தை அறியாது. Media query object addEventListener-ஐ ஆதரிக்கிறது, ஆனால் அதைச் சரியாக இணைப்பது, unmount செய்யும்போது அதை நீக்குவது மற்றும் பழைய addListener syntax-க்கான polyfill முறையைப் பயன்படுத்துவது போன்றவை அதிகப்படியான boilerplate குறியீடுகளை உருவாக்கி, copy-paste பிழைகளுக்கு வழிவகுக்கும்.
இரண்டாவதாக, SSR-ன் போது window இருக்காது. உங்கள் செயலி சர்வரில் render செய்யப்பட்டால், ஒரு சாதாரண matchMedia அழைப்பு reference error-ஐ உருவாக்கி render செயல்பாட்டைத் தடுத்துவிடும். இதனால், நீங்கள் அந்தச் சரிபார்ப்பைச் typeof window !== 'undefined' போன்ற guards-க்குள் சுற்ற வேண்டியிருக்கும், இயல்புநிலை (default) மதிப்பை ஊகித்துச் செயல்பட வேண்டியிருக்கும், மேலும் client hydration சரியாகப் பொருந்துமா என்று நம்ப வேண்டியிருக்கும்.
மூன்றாவதாக, ஒவ்வொரு அனிமேஷன் component-லும் அந்தத் தர்க்கத்தை (logic) மீண்டும் மீண்டும் பயன்படுத்துவது பராமரிப்புச் சுமையை (maintenance debt) அதிகரிக்கும். ஒரு குழு உறுப்பினர் listener-ஐ ஒரு விதமாகவும், மற்றொருவர் அதைத் தவிர்க்கவும், மூன்றாவது நபர் அனிமேஷனுக்கு முன்னுரிமை அளிக்கும் ஒரு default மதிப்பை நேரடியாகக் குறியீட்டில் (hard-code) எழுதவும் வாய்ப்புள்ளது. ஒரு hook இந்தச் சிக்கல்களைத் த centralize செய்கிறது.
useReducedMotion இந்த மூன்று சிக்கல்களையும் தீர்க்கிறது. இது ஒரு எளிய boolean மதிப்பைத் தருகிறது. இது சர்வரில் பாதுகாப்பாகச் செயல்படுகிறது (no-ops). மேலும், listener-ஐத் தானாகவே இணைத்து, தேவைப்படாதபோது நீக்கிவிடுகிறது.
இதைப் பயன்படுத்துவதற்கான மூன்று வழிகள்
உங்களிடம் boolean மதிப்பு கிடைத்தவுடன், அதற்கேற்ப செயல்பட ஒரு உத்தி தேவை. ஒரு தனி component முதல் முழுச் செயலி வரை பயன்படுத்தக்கூடிய மூன்று முறைகள் இதோ.
1. தேவையற்ற வேலைகளைத் தவிர்க்க CSS Classes-களைக் கட்டுப்படுத்துங்கள்
மிகவும் நேரடியான அணுகுமுறை என்னவென்றால், கனமான JavaScript animation loops தொடங்குவதைத் தடுப்பதாகும். ஒரு parallax image component-ஐக் கற்பனை செய்து கொள்ளுங்கள்; அது வழக்கமாக scroll events-களைக் கவனித்து, requestAnimationFrame loop-க்குள் அடுக்குகளை (layers) நகர்த்துகிறது. அந்தத் தர்க்கத்தை இயக்கிவிட்டு, பிறகு அதன் காட்சிகளைத் தடுப்பதற்குப் பதிலாக, முதலில் useReducedMotion-ஐச் சரிபார்க்கவும்.
அந்த hook true என்று அளித்தால், ஒரு static variant class-உடன் component-ஐ render செய்யவும், scroll listeners-களை இணைக்கும் useEffect-ஐத் தவிர்க்கவும். இதனால் உலாவியின் வேலை குறையும். இயக்க உணர்திறன் (motion sensitivity) கொண்ட பயனர்கள் ஒரு நிலையானப் படத்தைப் பார்ப்பார்கள். மற்றவர்களுக்கு நகரும் அடுக்குகளைப் பார்க்க முடியும். அனிமேஷன் குறியீடு தொடக்கத்திலேயே இயங்காததால், நீங்கள் CPU மற்றும் பேட்டரியைச் சேமிக்கலாம்.
2. அனிமேஷன் லைப்ரரிகளுக்கு நேரடியாகப் பயன்படுத்துங்கள்
நீங்கள் Framer Motion போன்ற ஒரு library-யைப் பயன்படுத்தினால், இந்த hook உங்கள் prop வரையறைகளிலேயே (definitions) நேரடியாகப் பொருந்தும். Motion components ஆகியவை variants, transitions மற்றும் gestures ஆகியவற்றிற்கான configuration objects-களை ஏற்கும். useReducedMotion-லிருந்து கிடைக்கும் boolean மதிப்பை வைத்து, transitions-களில் நிபந்தனைக்குட்பட்டு (conditionally) duration: 0 என அமைக்கலாம், அல்லது
