useContext

useContext என்பது உங்கள் component-இலிருந்து context-ஐ read செய்து subscribe செய்ய உதவும் React Hook ஆகும்.

const value = useContext(SomeContext)

மேற்கோள்

useContext(SomeContext)

உங்கள் component-ன் top level-இல் useContext-ஐ call செய்து context-ஐ read செய்து subscribe செய்யுங்கள்.

import { useContext } from 'react';

function MyComponent() {
const theme = useContext(ThemeContext);
// ...

மேலும் examples-ஐ கீழே பார்க்கவும்.

அளவுருக்கள்

  • SomeContext: நீங்கள் முன்பு createContext மூலம் create செய்த context. Context தானாக information-ஐ வைத்திருக்காது; components-இலிருந்து provide செய்யவோ read செய்யவோ முடியும் information வகையை மட்டும் அது குறிக்கிறது.

திரும்பும் மதிப்பு

useContext call செய்கிற component-க்கு context value-ஐ return செய்கிறது. Tree-இல் call செய்கிற component-க்கு மேல் இருக்கும் closest SomeContext-க்கு pass செய்யப்பட்ட value இதை தீர்மானிக்கிறது. அப்படிப்பட்ட provider எதுவும் இல்லையெனில், அந்த context-க்காக createContext-க்கு நீங்கள் pass செய்த defaultValue return செய்யப்படும். Return செய்யப்படும் value எப்போதும் up-to-date ஆக இருக்கும். ஏதேனும் context மாறினால், அதை read செய்யும் components-ஐ React automatic ஆக re-render செய்கிறது.

கவனிக்க வேண்டியவை

  • ஒரு component-இல் உள்ள useContext() call, அதே component return செய்யும் providers-ஆல் பாதிக்கப்படாது. பொருந்தும் <Context>, useContext() call செய்யும் component-க்கு மேலே இருக்க வேண்டும்.
  • வேறுபட்ட value பெறும் provider-இலிருந்து தொடங்கி, குறிப்பிட்ட context-ஐ use செய்யும் எல்லா children-ஐயும் React automatically re-render செய்கிறது. முந்தைய மற்றும் அடுத்த values Object.is comparison மூலம் ஒப்பிடப்படுகின்றன. memo மூலம் re-renders-ஐ skip செய்தாலும், children புதிய context values-ஐ பெறுவதை அது தடுக்காது.
  • உங்கள் build system output-இல் duplicate modules-ஐ உருவாக்கினால் (symlinks காரணமாக இது நடக்கலாம்), context உடையக்கூடும். Context வழியாக ஏதாவது pass செய்வது, context provide செய்ய நீங்கள் use செய்யும் SomeContext மற்றும் அதை read செய்ய நீங்கள் use செய்யும் SomeContext ஆகியவை === comparison-ல் தீர்மானிக்கப்படும் படி முழுமையாக அதே object ஆக இருந்தால் மட்டுமே வேலை செய்யும்.

பயன்பாடு

Tree-க்குள் ஆழமாக data pass செய்தல்

உங்கள் component-ன் top level-இல் useContext-ஐ call செய்து context-ஐ read செய்து subscribe செய்யுங்கள்.

import { useContext } from 'react';

function Button() {
const theme = useContext(ThemeContext);
// ...

நீங்கள் pass செய்த context-க்கான context value-ஐ useContext return செய்கிறது. Context value-ஐ தீர்மானிக்க, React component tree-ஐ தேடி, அந்த குறிப்பிட்ட context-க்கான மேலே உள்ள closest context provider-ஐ கண்டுபிடிக்கிறது.

ஒரு Button-க்கு context pass செய்ய, அதையோ அதன் parent components-இல் ஒன்றையோ பொருந்தும் context provider-க்குள் wrap செய்யுங்கள்:

function MyPage() {
return (
<ThemeContext value="dark">
<Form />
</ThemeContext>
);
}

function Form() {
// ... renders buttons inside ...
}

Provider மற்றும் Button இடையில் எத்தனை component layers இருந்தாலும் பரவாயில்லை. Form-க்கு உள்ளே எங்கிருந்தாலும் ஒரு Button useContext(ThemeContext) call செய்தால், அது value ஆக "dark"-ஐ பெறும்.

Pitfall

useContext() எப்போதும் அதை call செய்கிற component-க்கு மேலே உள்ள closest provider-ஐ தேடும். அது மேலே நோக்கி தேடும்; நீங்கள் useContext() call செய்யும் அதே component-இல் உள்ள providers-ஐ கருதாது.

import { createContext, useContext } from 'react';

const ThemeContext = createContext(null);

export default function MyApp() {
  return (
    <ThemeContext value="dark">
      <Form />
    </ThemeContext>
  )
}

function Form() {
  return (
    <Panel title="வரவேற்பு">
      <Button>பதிவு செய்</Button>
      <Button>உள்நுழை</Button>
    </Panel>
  );
}

function Panel({ title, children }) {
  const theme = useContext(ThemeContext);
  const className = 'panel-' + theme;
  return (
    <section className={className}>
      <h1>{title}</h1>
      {children}
    </section>
  )
}

function Button({ children }) {
  const theme = useContext(ThemeContext);
  const className = 'button-' + theme;
  return (
    <button className={className}>
      {children}
    </button>
  );
}


Context வழியாக pass செய்யப்பட்ட data-வை update செய்தல்

பல நேரங்களில், context காலப்போக்கில் மாற வேண்டும் என்று நீங்கள் விரும்புவீர்கள். Context-ஐ update செய்ய, அதை state-உடன் combine செய்யுங்கள். Parent component-இல் state variable-ஐ declare செய்து, current state-ஐ context value ஆக provider-க்கு கீழே pass செய்யுங்கள்.

function MyPage() {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext value={theme}>
<Form />
<Button onClick={() => {
setTheme('light');
}}>
Light theme-க்கு மாற்று
</Button>
</ThemeContext>
);
}

இப்போது provider-க்கு உள்ளே உள்ள எந்த Button-உம் current theme value-ஐ பெறும். Provider-க்கு pass செய்யும் theme value-ஐ update செய்ய setTheme call செய்தால், எல்லா Button components-உம் புதிய 'light' value உடன் re-render ஆகும்.

Context-ஐ update செய்வதற்கான examples

Example 1 of 5:
Context வழியாக ஒரு value-ஐ update செய்தல்

இந்த example-இல், MyApp component ஒரு state variable-ஐ வைத்திருக்கிறது; பின்னர் அது ThemeContext provider-க்கு pass செய்யப்படுகிறது. “Dark mode” checkbox-ஐ check செய்தால் state update ஆகும். Provide செய்யப்பட்ட value மாறும்போது, அந்த context-ஐ use செய்யும் எல்லா components-உம் re-render ஆகும்.

import { createContext, useContext, useState } from 'react';

const ThemeContext = createContext(null);

export default function MyApp() {
  const [theme, setTheme] = useState('light');
  return (
    <ThemeContext value={theme}>
      <Form />
      <label>
        <input
          type="checkbox"
          checked={theme === 'dark'}
          onChange={(e) => {
            setTheme(e.target.checked ? 'dark' : 'light')
          }}
        />
        Dark mode பயன்படுத்து
      </label>
    </ThemeContext>
  )
}

function Form({ children }) {
  return (
    <Panel title="வரவேற்பு">
      <Button>பதிவு செய்</Button>
      <Button>உள்நுழை</Button>
    </Panel>
  );
}

function Panel({ title, children }) {
  const theme = useContext(ThemeContext);
  const className = 'panel-' + theme;
  return (
    <section className={className}>
      <h1>{title}</h1>
      {children}
    </section>
  )
}

function Button({ children }) {
  const theme = useContext(ThemeContext);
  const className = 'button-' + theme;
  return (
    <button className={className}>
      {children}
    </button>
  );
}

value="dark" "dark" string-ஐ pass செய்கிறது, ஆனால் value={theme} JSX curly braces மூலம் JavaScript theme variable-ன் value-ஐ pass செய்கிறது என்பதை கவனிக்கவும். Curly braces, strings அல்லாத context values-ஐயும் pass செய்ய அனுமதிக்கின்றன.


Fallback default value-ஐ குறிப்பிடுதல்

Parent tree-இல் அந்த குறிப்பிட்ட context-க்கான providers எதையும் React கண்டுபிடிக்க முடியாவிட்டால், useContext() return செய்யும் context value, நீங்கள் அந்த context-ஐ create செய்தபோது குறிப்பிட்ட default value-க்கு சமமாக இருக்கும்:

const ThemeContext = createContext(null);

Default value ஒருபோதும் மாறாது. Context-ஐ update செய்ய வேண்டும் என்றால், மேலே விவரித்தபடி அதை state உடன் use செய்யுங்கள்.

பல நேரங்களில், null-க்கு பதிலாக default ஆக use செய்ய இன்னும் meaningful ஆன value இருக்கலாம், உதாரணமாக:

const ThemeContext = createContext('light');

இவ்வாறு செய்தால், பொருந்தும் provider இல்லாமல் தவறுதலாக ஏதேனும் component-ஐ render செய்தாலும் அது உடையாது. Tests-இல் பல providers setup செய்யாமல் test environment-இல் உங்கள் components நன்றாக வேலை செய்யவும் இது உதவும்.

கீழுள்ள example-இல், “Theme மாற்று” button எப்போதும் light ஆக இருக்கும்; ஏனெனில் அது எந்த theme context provider-க்கும் வெளியே உள்ளது, மேலும் default context theme value 'light'. Default theme-ஐ 'dark' ஆக edit செய்து முயற்சிக்கவும்.

import { createContext, useContext, useState } from 'react';

const ThemeContext = createContext('light');

export default function MyApp() {
  const [theme, setTheme] = useState('light');
  return (
    <>
      <ThemeContext value={theme}>
        <Form />
      </ThemeContext>
      <Button onClick={() => {
        setTheme(theme === 'dark' ? 'light' : 'dark');
      }}>
        Theme மாற்று
      </Button>
    </>
  )
}

function Form({ children }) {
  return (
    <Panel title="வரவேற்பு">
      <Button>பதிவு செய்</Button>
      <Button>உள்நுழை</Button>
    </Panel>
  );
}

function Panel({ title, children }) {
  const theme = useContext(ThemeContext);
  const className = 'panel-' + theme;
  return (
    <section className={className}>
      <h1>{title}</h1>
      {children}
    </section>
  )
}

function Button({ children, onClick }) {
  const theme = useContext(ThemeContext);
  const className = 'button-' + theme;
  return (
    <button className={className} onClick={onClick}>
      {children}
    </button>
  );
}


Tree-இன் ஒரு பகுதிக்காக context-ஐ override செய்தல்

Tree-இன் ஒரு பகுதியை வேறு value கொண்ட provider-க்குள் wrap செய்வதன் மூலம், அந்த பகுதிக்கான context-ஐ override செய்யலாம்.

<ThemeContext value="dark">
...
<ThemeContext value="light">
<Footer />
</ThemeContext>
...
</ThemeContext>

தேவைப்படும் அளவுக்கு providers-ஐ nest செய்து override செய்யலாம்.

Context-ஐ override செய்வதற்கான examples

Example 1 of 2:
Theme-ஐ override செய்தல்

இங்கே, Footer-க்கு உள்ளே இருக்கும் button, வெளியே உள்ள buttons ("dark") விட வேறுபட்ட context value ("light") பெறுகிறது.

import { createContext, useContext } from 'react';

const ThemeContext = createContext(null);

export default function MyApp() {
  return (
    <ThemeContext value="dark">
      <Form />
    </ThemeContext>
  )
}

function Form() {
  return (
    <Panel title="வரவேற்பு">
      <Button>பதிவு செய்</Button>
      <Button>உள்நுழை</Button>
      <ThemeContext value="light">
        <Footer />
      </ThemeContext>
    </Panel>
  );
}

function Footer() {
  return (
    <footer>
      <Button>அமைப்புகள்</Button>
    </footer>
  );
}

function Panel({ title, children }) {
  const theme = useContext(ThemeContext);
  const className = 'panel-' + theme;
  return (
    <section className={className}>
      {title && <h1>{title}</h1>}
      {children}
    </section>
  )
}

function Button({ children }) {
  const theme = useContext(ThemeContext);
  const className = 'button-' + theme;
  return (
    <button className={className}>
      {children}
    </button>
  );
}


Objects மற்றும் functions pass செய்யும்போது re-renders-ஐ optimize செய்தல்

Objects மற்றும் functions உட்பட எந்த values-ஐயும் context வழியாக pass செய்யலாம்.

function MyApp() {
const [currentUser, setCurrentUser] = useState(null);

function login(response) {
storeCredentials(response.credentials);
setCurrentUser(response.user);
}

return (
<AuthContext value={{ currentUser, login }}>
<Page />
</AuthContext>
);
}

இங்கே, context value இரண்டு properties கொண்ட JavaScript object; அவற்றில் ஒன்று function. MyApp re-render ஆகும் ஒவ்வொரு முறையும் (உதாரணமாக, route update-இல்), இது வேறு function-ஐச் சுட்டும் வேறு object ஆக இருக்கும். அதனால் useContext(AuthContext) call செய்யும் tree-இல் ஆழமான எல்லா components-ஐயும் React re-render செய்ய வேண்டி வரும்.

சிறிய apps-இல் இது பிரச்சினையல்ல. ஆனால் currentUser போன்ற underlying data மாறவில்லை என்றால், அவற்றை re-render செய்ய தேவையில்லை. அந்த உண்மையை React பயன்படுத்த உதவ, login function-ஐ useCallback-ஆல் wrap செய்து, object creation-ஐ useMemo-க்குள் wrap செய்யலாம். இது ஒரு performance optimization:

import { useCallback, useMemo } from 'react';

function MyApp() {
const [currentUser, setCurrentUser] = useState(null);

const login = useCallback((response) => {
storeCredentials(response.credentials);
setCurrentUser(response.user);
}, []);

const contextValue = useMemo(() => ({
currentUser,
login
}), [currentUser, login]);

return (
<AuthContext value={contextValue}>
<Page />
</AuthContext>
);
}

இந்த மாற்றத்தின் விளைவாக, MyApp re-render ஆக வேண்டியிருந்தாலும், currentUser மாறாத வரை useContext(AuthContext) call செய்யும் components re-render ஆக வேண்டியதில்லை.

useMemo மற்றும் useCallback பற்றி மேலும் படிக்கவும்.


சிக்கல் தீர்வு

என் component என் provider-இலிருந்து value-ஐ பார்க்கவில்லை

இது நடக்கும் சில common வழிகள் உள்ளன:

  1. useContext() call செய்யும் அதே component-இல் (அல்லது அதற்கு கீழே) நீங்கள் <SomeContext> render செய்கிறீர்கள். useContext() call செய்யும் component-க்கு மேலாகவும் வெளியிலும் <SomeContext>-ஐ நகர்த்துங்கள்.
  2. உங்கள் component-ஐ <SomeContext>-ஆல் wrap செய்ய மறந்திருக்கலாம், அல்லது நீங்கள் நினைத்ததைவிட வேறு tree பகுதியில் அதை வைத்திருக்கலாம். React DevTools பயன்படுத்தி hierarchy சரியாக உள்ளதா என்று check செய்யுங்கள்.
  3. உங்கள் tooling-இல் உள்ள build issue காரணமாக, provide செய்யும் component பார்க்கும் SomeContext மற்றும் read செய்யும் component பார்க்கும் SomeContext இரண்டு வேறு objects ஆக இருக்கலாம். உதாரணமாக, symlinks use செய்தால் இது நடக்கலாம். அவற்றை window.SomeContext1 மற்றும் window.SomeContext2 போன்ற globals-க்கு assign செய்து, console-இல் window.SomeContext1 === window.SomeContext2 என்பதை check செய்து இதை verify செய்யலாம். அவை ஒன்றாக இல்லையெனில், build tool level-இல் அந்த issue-ஐ fix செய்யுங்கள்.

Default value வேறாக இருந்தாலும் என் context-இலிருந்து எப்போதும் undefined கிடைக்கிறது

Tree-இல் value இல்லாத provider இருக்கலாம்:

// 🚩 Doesn't work: no value prop
<ThemeContext>
<Button />
</ThemeContext>

value-ஐ specify செய்ய மறந்தால், அது value={undefined} pass செய்வது போலாகும்.

நீங்கள் தவறுதலாக வேறு prop பெயரையும் பயன்படுத்தியிருக்கலாம்:

// 🚩 Doesn't work: prop should be called "value"
<ThemeContext theme={theme}>
<Button />
</ThemeContext>

இந்த இரு cases-இலும் console-இல் React-இலிருந்து warning காண வேண்டும். அவற்றை fix செய்ய, prop-ஐ value என்று அழைக்கவும்:

// ✅ Passing the value prop
<ThemeContext value={theme}>
<Button />
</ThemeContext>

உங்கள் createContext(defaultValue) call-இலிருந்து வரும் default value மேலே பொருந்தும் provider ஒன்றும் இல்லாதபோது மட்டுமே use செய்யப்படும் என்பதை கவனிக்கவும். Parent tree-இல் எங்காவது <SomeContext value={undefined}> component இருந்தால், useContext(SomeContext) call செய்யும் component context value ஆக undefined-ஐப் பெறும்.