React.js

Kirish

React.js bugungi kunda eng mashhur frontend kutubxonalardan biri. Lekin uni to'g'ri ishlatmasangiz, ilovangiz sekin ishlashi va kod boshqarilmaydigan holatga kelishi mumkin. Ushbu maqolada React bilan professional darajada ishlash uchun eng yaxshi amaliyotlarni ko'rib chiqamiz.

1. Komponent Strukturasi

Kichik va qayta ishlatiladigan komponentlar yarating

Har bir komponent faqat bitta vazifani bajarishi kerak (Single Responsibility Principle).

// ❌ Yomon - katta va murakkab komponent
function UserDashboard() {
    return (
        <div>
            <header>...</header>
            <nav>...</nav>
            <main>...</main>
            <footer>...</footer>
        </div>
    );
}

// ✅ Yaxshi - kichik, qayta ishlatiladigan komponentlar
function UserDashboard() {
    return (
        <div>
            <Header />
            <Navigation />
            <MainContent />
            <Footer />
        </div>
    );
}

Komponentlarni to'g'ri nomlash

// ❌ Yomon
function btn() { }
function usercard() { }

// ✅ Yaxshi - PascalCase
function Button() { }
function UserCard() { }

2. State Boshqaruvi

State'ni minimal darajada saqlang

F

aqat zarur bo'lgan ma'lumotlarni state'da saqlang. Hisoblangan qiymatlarni state'ga qo'ymang.

// ❌ Yomon - ortiqcha state
const [users, setUsers] = useState([]);
const [userCount, setUserCount] = useState(0);

useEffect(() => {
    setUserCount(users.length);
}, [users]);

// ✅ Yaxshi - hisoblangan qiymat
const [users, setUsers] = useState([]);
const userCount = users.length;

Ob'ektlarni immutable yangilang

// ❌ Yomon - to'g'ridan-to'g'ri o'zgartirish
const updateUser = () => {
    user.name = "Yangi ism";
    setUser(user);
};

// ✅ Yaxshi - yangi ob'ekt yaratish
const updateUser = () => {
    setUser({
        ...user,
        name: "Yangi ism"
    });
};

3. Performance Optimization

React.memo() - komponentni memoize qilish

Agar komponent props o'zgarmasa, qayta render qilinmasligi uchun React.memo() ishlatamiz.

import { memo } from 'react';

const UserCard = memo(({ user }) => {
    console.log('UserCard render');
    return (
        <div>
            <h3>{user.name}</h3>
            <p>{user.email}</p>
        </div>
    );
});

export default UserCard;

useMemo() - qimmat hisob-kitoblarni cache qilish

import { useMemo } from 'react';

function ProductList({ products, filter }) {
    // Faqat products yoki filter o'zgarganda qayta hisoblaydi
    const filteredProducts = useMemo(() => {
        console.log('Filtering...');
        return products.filter(p => p.category === filter);
    }, [products, filter]);

    return (
        <div>
            {filteredProducts.map(p => (
                <ProductCard key={p.id} product={p} />
            ))}
        </div>
    );
}

useCallback() - funksiyalarni cache qilish

import { useCallback } from 'react';

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

    // handleClick faqat count o'zgargandagina qayta yaratiladi
    const handleClick = useCallback(() => {
        console.log('Clicked:', count);
    }, [count]);

    return <Child onClick={handleClick} />;
}

⚠️ Muhim

useMemo va useCallback har doim ham kerak emas! Faqat performans muammosi bo'lganda ishlating. Ortiqcha ishlatish kod murakkablashtirib yuboradi.

4. Custom Hooks

Takrorlanuvchi logikani custom hook'larga ajrating.

Fetch uchun custom hook

// hooks/useFetch.js
import { useState, useEffect } from 'react';

function useFetch(url) {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
        const fetchData = async () => {
            try {
                const response = await fetch(url);
                const json = await response.json();
                setData(json);
            } catch (err) {
                setError(err);
            } finally {
                setLoading(false);
            }
        };

        fetchData();
    }, [url]);

    return { data, loading, error };
}

// Ishlatish
function Users() {
    const { data, loading, error } = useFetch('/api/users');

    if (loading) return <p>Yuklanmoqda...</p>;
    if (error) return <p>Xato: {error.message}</p>;

    return (
        <div>
            {data.map(user => (
                <UserCard key={user.id} user={user} />
            ))}
        </div>
    );
}

Form uchun custom hook

// hooks/useForm.js
import { useState } from 'react';

function useForm(initialValues) {
    const [values, setValues] = useState(initialValues);

    const handleChange = (e) => {
        setValues({
            ...values,
            [e.target.name]: e.target.value
        });
    };

    const reset = () => {
        setValues(initialValues);
    };

    return { values, handleChange, reset };
}

// Ishlatish
function LoginForm() {
    const { values, handleChange, reset } = useForm({
        email: '',
        password: ''
    });

    const handleSubmit = (e) => {
        e.preventDefault();
        console.log(values);
        reset();
    };

    return (
        <form onSubmit={handleSubmit}>
            <input
                name="email"
                value={values.email}
                onChange={handleChange}
            />
            <input
                name="password"
                type="password"
                value={values.password}
                onChange={handleChange}
            />
            <button type="submit">Kirish</button>
        </form>
    );
}

5. Code Splitting va Lazy Loading

Katta ilovalarni kichik qismlarga bo'lib, zarur bo'lganda yuklaymiz.

import { lazy, Suspense } from 'react';

// Lazy loading
const Dashboard = lazy(() => import('./pages/Dashboard'));
const Profile = lazy(() => import('./pages/Profile'));
const Settings = lazy(() => import('./pages/Settings'));

function App() {
    return (
        <Suspense fallback={<div>Yuklanmoqda...</div>}>
            <Routes>
                <Route path="/dashboard" element={<Dashboard />} />
                <Route path="/profile" element={<Profile />} />
                <Route path="/settings" element={<Settings />} />
            </Routes>
        </Suspense>
    );
}

6. Error Boundaries

Xatolarni tutish va foydalanuvchiga chiroyli ko'rinishda ko'rsatish.

import { Component } from 'react';

class ErrorBoundary extends Component {
    state = { hasError: false };

    static getDerivedStateFromError(error) {
        return { hasError: true };
    }

    componentDidCatch(error, errorInfo) {
        console.error('Error:', error, errorInfo);
    }

    render() {
        if (this.state.hasError) {
            return (
                <div>
                    <h2>Xatolik yuz berdi</h2>
                    <p>Iltimos, sahifani yangilang</p>
                </div>
            );
        }

        return this.props.children;
    }
}

// Ishlatish
function App() {
    return (
        <ErrorBoundary>
            <MyApp />
        </ErrorBoundary>
    );
}

7. Props Drilling Muammosini Hal Qilish

Context API

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

// Context yaratish
const ThemeContext = createContext();

// Provider
function ThemeProvider({ children }) {
    const [theme, setTheme] = useState('light');

    return (
        <ThemeContext.Provider value={{ theme, setTheme }}>
            {children}
        </ThemeContext.Provider>
    );
}

// Custom hook
function useTheme() {
    return useContext(ThemeContext);
}

// Ishlatish
function Button() {
    const { theme, setTheme } = useTheme();

    return (
        <button
            className={theme}
            onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
        >
            Theme: {theme}
        </button>
    );
}

8. TypeScript bilan ishlash

TypeScript kodni xavfsizroq va tushunarli qiladi.

// Props uchun interface
interface UserCardProps {
    user: {
        id: number;
        name: string;
        email: string;
        role?: 'admin' | 'user';
    };
    onDelete?: (id: number) => void;
}

const UserCard: React.FC<UserCardProps> = ({ user, onDelete }) => {
    return (
        <div className="user-card">
            <h3>{user.name}</h3>
            <p>{user.email}</p>
            {user.role && <span>{user.role}</span>}
            {onDelete && (
                <button onClick={() => onDelete(user.id)}>
                    O'chirish
                </button>
            )}
        </div>
    );
};

9. Testing

Komponentlarni test qilish kod sifatini oshiradi.

import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';

test('counter increment ishlaydi', () => {
    render(<Counter />);

    const button = screen.getByText('Increment');
    const count = screen.getByText('Count: 0');

    fireEvent.click(button);

    expect(count).toHaveTextContent('Count: 1');
});

✅ Best Practices Checklist

  • Komponentlarni kichik va sodda qiling
  • State'ni minimal saqlang
  • Props'ni destructure qiling
  • Key prop'ni to'g'ri ishlating
  • useEffect dependency array'ini unutmang
  • Custom hook'lar yarating
  • Code splitting qiling
  • TypeScript ishlating
  • Test yozing
  • ESLint va Prettier o'rnating

Xulosa

React.js bilan professional darajada ishlash uchun bu amaliyotlarni doimo yodda tuting. Kod sifati va performans bir-biriga bog'liq - yaxshi yozilgan kod tez ishlaydi va boshqarilishi oson.

Keyingi maqolalarda ko'ramiz:

Maqolani ulashing

Malika Yusupova

Malika Yusupova

4 yillik React tajribasiga ega Tech Lead. Udevs kompaniyasida katta jamoaga rahbarlik qiladi. React va Frontend arxitektura bo'yicha mutaxassis.