March 8, 2022

React qo'llanma 2-qism

Quyida siz bilishingiz kerak bo'lgan Reactning muhim mavzularini qisqa va aniq tushuntirishga harakat qilaman.(...davomi)

Ko'rib chiqiladigan mavzular:

  • Context nima?
  • Hooklar
  • useState() haqida
  • useEffect() haqida
  • useRef()
  • useContext()
  • useCallback()
  • useMemo()

Context haqida:

React context bizga propsni ishlatmasdan componetnlar aro ma'lumot almashishimizga yordam beradi. Ba'zida props orqali ma'lumot yuborsak, o'sha ma'lumotni ishlatmaydigan componentda ham propsdan foydalanishimiz kerak bo'ladi. Bu muammo props drilling deb ataladi.

Quyidagi misolda Body componenti o'ziga kerak bo'lmagan ma'lumotni qabul qilmoqda.

function App() {
  return (
    <Body name="John Doe" />
  );
} 

function Body({ name }) {
  return (
    <Greeting name={name} />
  );
} 

function Greeting({ name }) {
  return <h1>Welcome, {name}</h1>;
}

Bu muammoni Context orqali hal etishimiz mumkin. Context ni ishlatishimiz uchun biz Reactning createContext funksiyasidan foydalanamiz. Biz uni boshlang'ich qiymat bilan chaqira olamiz. Hosil qilingan contextning Provider va Consumer propertylari mavjud. Bu propertylar componentlar hisoblanadi. Biz qaysi componentlarga berilgan ma'lumotni yubormoqchi bo'lsak o'sha componentni Provider bilan o'raymiz. Ma'lumotni ishlatmoqchi bo'lgan joyimizda esa Consumer dan foydalanamiz.

import { createContext } from 'react';

const NameContext = createContext('');

function App() {
  return (
    <NameContext.Provider value="John Doe">
      <Body />
    <NameContext.Provider>
  );
} 

function Body() {
  return <Greeting />;
} 

function Greeting() {
  return (
    <NameContext.Consumer>
      {name => <h1>Welcome, {name}</h1>}
    </NameContext.Consumer>
  );
}

React Hooks:

Hooklar reactning 16.8 chi versiyasida bizga tanishtirildi. Ular React function componentlarga qayta ishlatiladigan va o'zgaruvchan ma'lumotlarni oson qo'shish yo'li hisoblanadi. Hooklar bizga oldinlari faqatgina Class Componentlarda mavjud bo'lgan barcha hususiyatlardan foydalanish imkonini taqdim etadi. Va yana biz o'zimizning custom hook imizni ham yaratishimiz mumkin. React kutubxonasida juda ko'p hooklar mavjud. Biz esa faqat 6ta eng muhimlarini ko'rib chiqamiz.

  • useState
  • useEffect
  • useRef
  • useContext
  • useCallback
  • useMemo

React useState Hook:

useState() - nomidan ko'rinib turibdiki, bu hook orqali biz function componentlarda o'zgaruvchan ma'lumotlar bilan ishlay olamiz. useState()ni oddiy o'zgaruvchilarning o'rnida ishlata olamiz, chunki qachon ma'lumot(holat) o'zgaradigan bo'lsa, componentimiz ham render bo'ladi va yangi ma'lumotni ko'rsatadi. Boshqa hooklar kabi biz useState() ni componentning avvalida chaqiramiz va unga boshlang'ich qiymat bera olamiz. useState() qaytaradigan ma'lumotni biz array destructing orqali qabul qilib olamiz. Birinchisi bizning saqlab qo'ygan ma'lumotimiz hisoblanadi, ikkinchisi esa ma'lumotni yangilash uchun kerak bo'ladigan funksiyadir.

import { useState } from 'react';

function MyComponent() {
  const [stateValue, setStateValue] = useState(initialValue);
}

useState() ni oddiy hisoblagich yasash orqali ishlatib ko'ramiz. Biz count o'zgaruvchisidagi hozirgi qiymatni setCount ga count + 1 ni berish orqali 1ga oshirishimiz mumkin.

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  function updateCount() {
    setCount(count + 1);
  }

  return <button onClick={updateCount}>Count is: {count}</button>;
}

React useEffect() hook:

Agar biz "tashqi dunyo" bilan aloqada bo'lishni hohlasak, masalan API dan foydalanishni, biz useEffect() hookini ishlatamiz. useEffect() side effectlarni bajarish uchun ishlatiladi, ya'ni dasturimiz tashqarisidagi va natijasini oldindan aytib bo'lmaydigan operatsiyalarni bajarish uchun biz useEffect() dan foydalanamiz. useEffect()ning sintaksisi oson, birinchi argument sifatida funksiya qabul qilsa, ikkinchi argument sifatida esa array qabul qiladi.

import { useEffect } from 'react';

function MyComponent() {
   useEffect(() => {
        // side effect ni bu yerda bajaring
   }, []);
}

Agar biz ma'lumotni fetch qilmoqchi bo'lsak, ma'lumotni yuklab olish va sahifada ko'rsatish uchun useEffect()dan quyidagicha foydalanamiz.

import { useEffect } from 'react';

function PostList() {
	 const [posts, setPosts] = useState([]);

   useEffect(() => {
	   fetch('https://jsonplaceholder.typicode.com/posts')
       .then(response => response.json())
       .then(posts => setPosts(posts));
   }, []);

   return posts.map(post => <Post key={post.id} post={post} />
}

Agar biz effect funksiyasidan tashqarida bo'lgan biror qiymatni ishlatmoqchi bo'lsak, u holda bu qiymatni dependency arrayiga(useEffectning ikkinchi qiymati) berib qo'yishimiz kerak bo'ladi. Shunda qiymat o'zgaradigan bo'lsa useEffect() ham qayta ishga tushadi. Misol uchun, mobile menu ochilgan bo'lsa bodyga "overflow-hidden" class i qo'shilsin, yopiq bo'lsa olib tashlansin buyrug'ini bajaruvchi funksiya quyidagi ko'rinishda bo'ladi.

function Mobile({ open }) {
  useEffect(() => {
    const body = document.querySelector("#__next");

    if (open) {
      body.classList.add("overflow-hidden");
    } else {
      body.classList.remove("overflow-hidden");
    }
  }, [open]);
 
  // ...
}

React useRef() hook haqida:

useRef() bizga JSX elementini to'g'ridan to'g'ri boshqarish imkonini beradi. useRef() ni ishlatish uchun u chaqirilganda qaytarilgan qiymatni saqlab olib, uni berilgan elementning ref nomli propiga berib qo'yish kerak. ref propi React componentlarda emas faqat react elementlarda mavjud ekanligini ham bilib olish kerak. Quyida useRef() ning oddiy sintaksisi.

import { useRef } from 'react';

function MyComponent() {
  const ref = useRef();

  return <div ref={ref} />
}

React elementga ref biriktirganimizda, elementning o'zini boshqairish uchun ref.current dan foydalanamiz. Misol uchun, qachonki foydalanuvchi ctrl + k tugmalarini birgalikda bosganda qidiruv inputi focus holatga kelishini istasak quyidagicha code yozishimiz kerak bo'ladi.

import { useWindowEvent } from "@mantine/hooks";
import { useRef } from "react";

function Header() {
	const inputRef = useRef();

  useWindowEvent("keydown", (event) => {
    if (event.code === "KeyK" && event.ctrlKey) {
      event.preventDefault();
      inputRef.current.focus();
    }
  });
  
  return <input ref={inputRef} />
}

React useContext() hook:

useContext() contextni ishlatishimiz uchun Context.Consumer componentiga nisbatan ancha oson yo'l hisoblanadi. useContext() ning sintaksisi hosil qilingan Context obyektini useContextga atribut sifatida berib yuborishimizdan iborat. va useContext Context.Provider componentining value prop ida berib yuborgan qiymatimizni qaytarib beradi.

import { createContext, useContext } from 'react';

const NameContext = createContext('');

function App() {
  return (
    <NameContext.Provider value="John Doe">
      <Body />
    <NameContext.Provider>
  );
} 

function Body() {
  return <Greeting />;
} 

function Greeting() {
	const name = useContext(NameContext);

  return (
    <h1>Welcome, {name}</h1>
  );
}

React useCallback():

useCallback() har safar componentlarimiz re-render bo'lganida, funksiyalarning qayta yaratilishini oldini oladi, yo'qsa dasturimizning ishlashiga zarar yetishi mumkin. Agar biz avvalgi Davlatlar misoliga qaytadigan bo'lsak va yangi davlat qo'shish imkoniyatini ham qo'shsak, davlatni o'chirish funksiyasini esa props orqali berib yuborsak, bu funksiya har safar qayta yaratilishiga to'g'ri keladi. buni oldini olish uchun biz useCallback() dan foydalanamiz.

function App() {
  const [davlat, setDavlat] = React.useState("");
  const [davlats, setDavlats] = React.useState(["Uzbekistan", "Misr", "Turkiya"]);

  function handleChangeInput(event) {
    setDavlat(event.target.value);
  }
  function handleAddDavlat() {
    setDavlats(davlats.concat(davlat));
  }
  const handleRemoveDavlat = useCallback(davlat=> {
    setDavlats(davlats.filter((d) => d !== davlat));
  }, [davlats])

  return (
    <>
      <input onChange={handleChangeInput} />
      <button onClick={handleAddDavlat}>Add Davlat</button>
      <DavlatList davlats={davlats} handleRemoveDavlat={handleRemoveDavlat} />
    </>
  );
}

function DavlatList({ davlats, handleRemoveDavlat }) {
  return (
    <ul>
      {davlats.map((davlat) => (
        <li key={davlat} onClick={() => handleRemoveDavlat(davlat)}>
          {davlat}
        </li>
      ))}
    </ul>
  );
}

Agar biz davlatni o'chirish fuksiyasini useCallback() bilan o'ramaganimizda, har safar komponent render bo'lganda funksiya qayta yaratilgan bo'lar edi. useCallback()ning dependency array iga davlats qiymatini berganimiz uchun faqatgina davlats o'zgaradigan bo'lsa funksiya qayta yaratiladi.

React useMemo:

useMemo() berilgan operatsiyani eslab qolishimizga yordam beradi. Biz biror kattaroq qiymat qaytaruvchi funksiya yaratdik va u har component render bo'lganda qayta ishga tushmasligi uchun bizga useMemo() kerak bo'ladi. useEffect() va useCallback() lar kabi useMemo() ham callback funksiya va dependency qabul qiladi, ammo bu ikki funksiyaga o'xshamagn holda useMemo() qiymat qaytaradi. Qiymat return bilan qaytarilishi zarur. Quyidagi misolda biz useMemo() dan mdx-bundler kutubxonasi orqali yaratilgan komponentni eslab qolamiz va asosiy Post componentimiz render bo'lganida mdx-bundler orqali qayta component yaratilishini oldini olamiz.

import * as React from 'react'
import {getMDXComponent} from 'mdx-bundler/client'

function Post({code, frontmatter}) {
  const Component = React.useMemo(() => getMDXComponent(code), [code]);

  return (
    <>
      <header>
        <h1>{frontmatter.title}</h1>
        <p>{frontmatter.description}</p>
      </header>
      <main>
        <Component />
      </main>
    </>
  )
}

useMemo()ning dependencyiga code qiymatini berganimiz uchun qachonki code qiymati o'zgargandagina mdx-bundler qayta ishga tushadi.

Reed Barger maqolasi asosida tayyorlandi.