اذهب إلى المحتوى

السؤال

نشر

أفهم أنه لا يفترض استدعاء خطافات React داخل حلقة، ولكن لست متأكدًا من ما إذا كان هناك بديل أمثل، إن وجد.

على سبيل المثال، في الكود التالي:

import { useState, useEffect } from "react";

export default () => {
  const userIds = [1, 2, 3];
  const users = [];

  for (let userId of userIds) {
    const user = useFetchUser(userId);

    users.push(user);
  }

  return (
    <div>
      <h1>Users</h1>
      {users.map((user) => (
        <div>
          {user.id} - {user.name}
        </div>
      ))}
    </div>
  );
};

const useFetchUser = (id) => {
  const nameMap = {
    1: "Alice",
    2: "Bob",
    3: "Carol",
  };
  const [user, setUser] = useState({});

  useEffect(() => {
    setTimeout(() => {
      const name = nameMap[id];

      setUser({
        id,
        name,
      });
    }, 1000);
  }, [id]);

  return user;
};

ذلك ليس مستحسنًا (ولكن يعمل) لأنه يشمل استدعاء هوك (useFetchUser) داخل حلقة، فما هي الطريقة الأمثل للتعامل مع هذا الوضع؟

أول فكرة تتبادر إلى ذهني هي إنشاء خطاف useFetchUsers يستعين بجميع المستخدمين بدلاً من مستخدم واحد فقط، ولكن  لا يعمل.

const useFetchUsers = (ids) => {
  const users = [];

  for (let id of ids) {
    const user = useFetchUser(id);

    users.push(user);
  }

  return users;
};

أو على الأقل يعطي الخطأ التالي:

React Hook "useFetchUser" may be executed more than once. Possibly because it is called in a loop. React Hooks must be called in the exact same order in every component render. (react-hooks/rules-of-hooks)eslint

 

Recommended Posts

  • 0
نشر

الطريقة الأفضل لتجنب استدعاء الهوك داخل حلقة هي استخدام خطاف useMemo:

const users = useMemo(() => {
  return userIds.map(userId => useFetchUser(userId))
}, [userIds])

return (
  <div>
    {users.map(user => (
      <div key={user.id}>
        {user.id} - {user.name}  
      </div>
    ))}
  </div>
)

useMemo سيضمن أن يتم استدعاء useFetchUser مرة واحدة لكل مستخدم، بدلاً من داخل حلقة.

ويعتمد users على userIds فقط، فعندما يتغير userIds سيتم إعادة إنشاء users.

هذه الطريقة تجنب المشاكل التي تحدث عند استدعاء الهوك داخل حلقة، وتضمن أن يتم استدعاء useFetchUser بالترتيب الصحيح.

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...