بناء تطبيق كامل باستخدام React

الدرس السادس والعشرون: بناء تطبيق كامل باستخدام React

في هذا الدرس، سنتعلم كيفية بناء تطبيق ويب بسيط باستخدام React. سنتناول كيفية إدارة الحالة باستخدام useState و useReducer، بالإضافة إلى كيفية الاتصال بـ API وعرض البيانات في واجهة المستخدم.

1. إنشاء تطبيق بسيط باستخدام React

لنفترض أننا نريد بناء تطبيق بسيط لعرض قائمة من المستخدمين من API، حيث يمكن للمستخدمين إضافة وحذف الأشخاص من القائمة. سنبدأ أولاً بإعداد بيئة العمل وإنشاء تطبيق React باستخدام create-react-app.

إنشاء مشروع React:

npx create-react-app user-list-app
cd user-list-app
npm start

2. إعداد الـ Components

بناءً على متطلبات التطبيق، سنحتاج إلى مكونات أساسية مثل:

  • UserList: لعرض قائمة المستخدمين.
  • AddUserForm: لإضافة مستخدم جديد.
  • UserItem: لعرض كل مستخدم في القائمة.

المكون الأول: UserList

يُستخدم هذا المكون لعرض قائمة المستخدمين التي سيتم جلبها من الـ API.

import React, { useState, useEffect } from 'react';
import UserItem from './UserItem';

const UserList = () => {
  const [users, setUsers] = useState<any[]>([]);
  const [loading, setLoading] = useState<boolean>(true);
  
  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(response => response.json())
      .then(data => {
        setUsers(data);
        setLoading(false);
      })
      .catch(error => {
        console.error('Error fetching data:', error);
        setLoading(false);
      });
  }, []);
  
  if (loading) return <p>Loading...</p>;
  
  return (
    <div>
      <h2>User List</h2>
      <ul>
        {users.map(user => (
          <UserItem key={user.id} user={user} />
        ))}
      </ul>
    </div>
  );
};

export default UserList;

الشرح:

  • useState: نستخدم useState لتخزين قائمة المستخدمين وحالة التحميل.
  • useEffect: نقوم بجلب البيانات من API باستخدام useEffect عند تحميل المكون.
  • UserItem: نمرر كل مستخدم إلى مكون UserItem لعرض التفاصيل.

المكون الثاني: UserItem

المكون UserItem يعرض كل مستخدم في القائمة.

import React from 'react';

const UserItem = ({ user }: { user: any }) => {
  return (
    <li>
      <p>{user.name}</p>
      <p>{user.email}</p>
    </li>
  );
};

export default UserItem;

الشرح:

  • props: نمرر user كمُدخل إلى المكون لعرض المعلومات الخاصة بالمستخدم.

المكون الثالث: AddUserForm

في هذا المكون، سنتعامل مع إضافة مستخدم جديد إلى القائمة.

import React, { useState } from 'react';

const AddUserForm = ({ onAddUser }: { onAddUser: (name: string, email: string) => void }) => {
  const [name, setName] = useState<string>('');
  const [email, setEmail] = useState<string>('');
  
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (!name || !email) return;
    onAddUser(name, email);
    setName('');
    setEmail('');
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        placeholder="Name"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
      <input
        type="email"
        placeholder="Email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      <button type="submit">Add User</button>
    </form>
  );
};

export default AddUserForm;

الشرح:

  • useState: نستخدم useState لإدارة قيم المدخلات (name و email).
  • onAddUser: عندما يرسل المستخدم النموذج، نقوم بإرسال البيانات المدخلة إلى المكون الأب.

3. إدارة الحالة باستخدام useState و useReducer

استخدام useState:

كما رأينا في المكونات السابقة، نستخدم useState لإدارة حالة المدخلات وحالة التحميل. هو الخيار الأمثل في حالات بسيطة مثل إضافة أو تعديل العناصر.

استخدام useReducer:

في حالة كان لدينا إدارة حالة معقدة (مثال: إدارة حالة متعددة العمليات أو مكونات متعددة)، يمكننا استخدام useReducer.

سنقوم بتطوير التطبيق باستخدام useReducer لإدارة قائمة المستخدمين.

import React, { useReducer, useEffect } from 'react';

interface User {
  id: number;
  name: string;
  email: string;
}

type Action =
  | { type: 'SET_USERS'; payload: User[] }
  | { type: 'ADD_USER'; payload: User };

const initialState: { users: User[] } = {
  users: [],
};

const userReducer = (state: typeof initialState, action: Action) => {
  switch (action.type) {
    case 'SET_USERS':
      return { ...state, users: action.payload };
    case 'ADD_USER':
      return { ...state, users: [...state.users, action.payload] };
    default:
      return state;
  }
};

const UserList = () => {
  const [state, dispatch] = useReducer(userReducer, initialState);
  
  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then(response => response.json())
      .then(data => {
        dispatch({ type: 'SET_USERS', payload: data });
      })
      .catch(error => {
        console.error('Error fetching data:', error);
      });
  }, []);
  
  const addUser = (name: string, email: string) => {
    const newUser = { id: Date.now(), name, email }; // باستخدام id موقت
    dispatch({ type: 'ADD_USER', payload: newUser });
  };
  
  return (
    <div>
      <h2>User List</h2>
      <ul>
        {state.users.map(user => (
          <UserItem key={user.id} user={user} />
        ))}
      </ul>
      <AddUserForm onAddUser={addUser} />
    </div>
  );
};

export default UserList;

الشرح:

  • useReducer: نستخدم useReducer بدلاً من useState لإدارة الحالة المعقدة. نمرر userReducer كدالة لتحديث الحالة بناءً على نوع الحدث.
  • Action: نحدد نوع الحدث (إضافة مستخدم أو تعيين قائمة المستخدمين).
  • dispatch: نرسل الأحداث إلى dispatch لتحديث الحالة.

4. الاتصال بـ API وعرض البيانات في واجهة المستخدم

كما هو موضح في المكونات السابقة، نستخدم fetch لجلب البيانات من API عند تحميل التطبيق باستخدام useEffect. يتم تخزين البيانات المسترجعة في الحالة ويتم عرضها في واجهة المستخدم.

5. الملخص

في هذا الدرس، قمنا ببناء تطبيق بسيط باستخدام React يتكون من المكونات التالية:

  • UserList لعرض قائمة المستخدمين.
  • AddUserForm لإضافة مستخدمين جدد.
  • UserItem لعرض كل مستخدم في القائمة.

استخدمنا useState و useReducer لإدارة الحالة في التطبيق، ووضحنا كيفية الاتصال بـ API باستخدام fetch لعرض البيانات في واجهة المستخدم.


اكتشاف المزيد من كود التطور

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

اترك رد

Scroll to Top