2 min read

React Context

React'ta bazı nesnelere global olarak erişebilmek isteriz. Örneğin kullanıcı kimliği, dil seçimi, tema seçimi gibi değerler uygulamanın bütününe etki edebilen değişkenlerdir.

Bu tarz durumlarda props passing yöntemiyle devamlı alt bileşenlere parametre göndermek çok fazla gereksiz kod tekrarına yol açar. Bundan kaçınabilmek için global değişkenlere direkt erişebileceğimiz bir yapı bulunuyor. Context yapısıyla global değişkenlere herhangi bir bileşenden erişebiliyoruz.

Temanın global değişkende tutulması: props passing ile iletme

Bir tema örneği verelim. Eğer dark tema seçilmişse bileşenlerdeki metin rengi ve arkaplanı buna göre değiştirelim.

const TimerComp = ({theme})=>{
const [secs,setSecs] = React.useState(0);
React.useEffect(()=>{
	const interval = setInterval(() => {    
    setSecs(prev=>prev+1);
  }, 1000);
  return () => clearInterval(interval);
},[]);
return(<p style={
theme==="dark"?
{color:"#fff",backgroundColor:"#20262E"}:
{color:"#20262E",backgroundColor:"#fff"}
}>Time since mount: {secs} seconds.</p>)
}

const theme = "dark";

const App = () => { 
 
  return (
    <div>     
      <TimerComp theme={theme} />     
    </div>
  );
};

ReactDOM.render(<App />, document.querySelector("#app"))

Burada tema değişkeni props passing yöntemiyle alt bileşene aktarılıyor. Bu sayede alt bileşen arkaplanı koyu renk olacak şekilde render ediliyor.

Bu örnekte bir sorun görünmüyor olsa da, bunun alt alta bileşenlere devamlı iletildiği bir senaryoyu düşünürsek zincirleme bir kod tekrarı olacağını tahmin edebiliriz.

useContext() ile global değerin okunması

Aynı işlemi bu kez Context ile yapalım. Function component içerisinde useContext() hook üzerinden global tema değişkenine erişelim.

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee"
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222"   
  }
};

const ThemeContext = React.createContext(themes.light);

function App() {
  return (
    <ThemeContext.Provider value={themes.dark}>
       <ThemedBox />
    </ThemeContext.Provider>
  );
}

function ThemedBox() {
const theme = React.useContext(ThemeContext);
  return (
    <div style={{ width:100,padding:10, background: theme.background, color: theme.foreground }}>
     <p>Themed box</p>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("app"));

Yukarıdaki örnekte görüldüğü gibi ThemedBox componenti herhangi bir props almıyor. Bunun yerine useContext() hook ile tema değerini okuyor.

useContext() ile global değerin değiştirilmesi

useContext() hook ile global bir değeri okumanın yanısıra, bu değerin değişimine de abone oluruz. Yani tema değişirse bu componentler yeniden render edilir.

Bir örnekle görelim. Burada bir butona tıklandığında temanın değişmesini sağlayan fonksiyon çağrılıyor. Tema değeri değişince de iki bileşen de yeniden render edilerek yeni temaya adapte olmuş oluyor.

const themes = {
  light: {
    foreground: "#000000",
    background: "#eeeeee",
   
  },
  dark: {
    foreground: "#ffffff",
    background: "#222222",   
  }
};

const ThemeContext = React.createContext(themes.light);

function App() {
const [theme,setTheme] = React.useState(themes.dark);
const toggleTheme = () =>{
	setTheme(prev=>prev===themes.dark?themes.light:themes.dark);
}
  return (
    <ThemeContext.Provider value={{theme,toggleTheme}}>
      <Toolbar />
      <ThemedBox />
    </ThemeContext.Provider>
  );
}

const Toolbar = () =>(<div>  <ThemedButton />    </div>  );


function ThemedButton() {
  const {theme,toggleTheme} = React.useContext(ThemeContext);
  return (
    <button style={{ background: theme.background, color: theme.foreground }}
    onClick={toggleTheme}
    >
      Click to toggle theme
    </button>
  );
}
function ThemedBox() {
  const {theme,toggleTheme} = React.useContext(ThemeContext);
  return (
    <div style={{ width:100,padding:10, background: theme.background, color: theme.foreground }}   
    >
     <p>Themed box</p>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("app"));

Bu şekilde Context API'yi kullanarak kullanıcının authorization bilgisi, tema veya dil seçimi gibi bütün uygulamaya etki eden değişkenleri herhangi bir kod satırdan okuyabilir ve değişimlere abone olarak yeniden render edilmesini sağlayabiliyoruz.