Kodax

State و useState — مقدمة React

State وuseState

State هي البيانات المتغيرة داخل المكون التي تُسبب إعادة الرسم عند تغييرها.

useState Hook

import { useState } from 'react';

function Counter() {
  // [القيمة, دالة التحديث] = useState(القيمة الأولية)
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>العداد: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        زيادة
      </button>
    </div>
  );
}

أنواع State

1. أرقام ونصوص

const [age, setAge] = useState(25);
const [name, setName] = useState("أحمد");
const [isActive, setIsActive] = useState(false);

2. Objects

const [user, setUser] = useState({
  name: "أحمد",
  email: "ahmed@email.com"
});

// ❌ خطأ - لا تُعدّل مباشرة
user.name = "محمد";
setUser(user);

// ✅ صحيح - أنشئ نسخة جديدة
setUser({ ...user, name: "محمد" });

// ✅ أو باستخدام دالة
setUser(prevUser => ({
  ...prevUser,
  name: "محمد"
}));

3. Arrays

const [items, setItems] = useState([]);

// إضافة عنصر
setItems([...items, newItem]);

// حذف عنصر
setItems(items.filter(item => item.id !== idToDelete));

// تحديث عنصر
setItems(items.map(item => 
  item.id === idToUpdate 
    ? { ...item, name: newName }
    : item
));

أمثلة عملية

نموذج تسجيل

function SignupForm() {
  const [formData, setFormData] = useState({
    username: "",
    email: "",
    password: ""
  });
  const [errors, setErrors] = useState({});
  const [isSubmitting, setIsSubmitting] = useState(false);
  
  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData(prev => ({
      ...prev,
      [name]: value
    }));
  };
  
  const handleSubmit = async (e) => {
    e.preventDefault();
    setIsSubmitting(true);
    
    try {
      // إرسال البيانات
      await submitForm(formData);
    } catch (error) {
      setErrors({ submit: error.message });
    } finally {
      setIsSubmitting(false);
    }
  };
  
  return (
    <form onSubmit={handleSubmit}>
      <input
        name="username"
        value={formData.username}
        onChange={handleChange}
        placeholder="اسم المستخدم"
      />
      <input
        name="email"
        type="email"
        value={formData.email}
        onChange={handleChange}
        placeholder="البريد الإلكتروني"
      />
      <input
        name="password"
        type="password"
        value={formData.password}
        onChange={handleChange}
        placeholder="كلمة المرور"
      />
      <button disabled={isSubmitting}>
        {isSubmitting ? "جارٍ التسجيل..." : "تسجيل"}
      </button>
    </form>
  );
}

قائمة المهام

function TodoList() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState("");
  
  const addTodo = () => {
    if (!input.trim()) return;
    
    setTodos([
      ...todos,
      {
        id: Date.now(),
        text: input,
        completed: false
      }
    ]);
    setInput("");
  };
  
  const toggleTodo = (id) => {
    setTodos(todos.map(todo =>
      todo.id === id
        ? { ...todo, completed: !todo.completed }
        : todo
    ));
  };
  
  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };
  
  return (
    <div>
      <input
        value={input}
        onChange={(e) => setInput(e.target.value)}
        onKeyDown={(e) => e.key === "Enter" && addTodo()}
        placeholder="مهمة جديدة..."
      />
      <button onClick={addTodo}>إضافة</button>
      
      <ul>
        {todos.map(todo => (
          <li key={todo.id}>
            <input
              type="checkbox"
              checked={todo.completed}
              onChange={() => toggleTodo(todo.id)}
            />
            <span style={{
              textDecoration: todo.completed ? "line-through" : "none"
            }}>
              {todo.text}
            </span>
            <button onClick={() => deleteTodo(todo.id)}>
              حذف
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
}

قواعد مهمة

1. لا تُعدّل State مباشرة - استخدم دالة التحديث

2. State غير متزامن - لا تعتمد على قيمته فوراً

3. استخدم الدالة للتحديث بناءً على القيمة السابقة

4. أنشئ State منفصلة للبيانات المختلفة

import { useState } from 'react';

function ShoppingCart() {
  const [items, setItems] = useState([]);
  const [total, setTotal] = useState(0);
  
  const addItem = (product) => {
    setItems([...items, { ...product, id: Date.now() }]);
    setTotal(prev => prev + product.price);
  };
  
  const removeItem = (id, price) => {
    setItems(items.filter(item => item.id !== id));
    setTotal(prev => prev - price);
  };
  
  return (
    <div className="cart">
      <h2>سلة التسوق ({items.length})</h2>
      
      {items.map(item => (
        <div key={item.id} className="cart-item">
          <span>{item.name}</span>
          <span>{item.price} دينار</span>
          <button onClick={() => removeItem(item.id, item.price)}>
            ✕
          </button>
        </div>
      ))}
      
      <div className="total">
        المجموع: {total} دينار
      </div>
    </div>
  );
}
اختبر فهمك