الدخول
مرحبا عزيزي القارئ!
منذ بعض الوقت (حوالي عام) ، واجهتني الحاجة إلى عرض المكونات في ReactJS بشكل مشروط ، اعتمادًا على حقوق المستخدم الحالية. أول شيء بدأته في البحث عن حلول جاهزة و "أفضل الممارسات". أعجب مقال "
التفويض القائم على الأدوار في رد الفعل "
بشدة باستخدامه
لمكونات النظام الأعلى (HOC). لكن للأسف ، لم أجد حلا يرضيني.
على ما يبدو ، بعد كل شيء ، فاته شيء ...... أو لم يكن يعرف عن وجود السياقات. في وقت كتابة هذا التقرير ، صادفت
إجابة رائعة
في تدفق مكدس . انتهى بي الأمر إلى حل مماثل للغاية.
في ذلك الوقت ، كنت معتادًا قليلاً على التفاعل المتفاعل (وحدة npm) ، وقد أعجبني كثيرًا نهج الزخرفة المستخدم في وظيفة الاتصال. يمكن العثور على تحليل مفصل لجهاز الاتصال
هنا .
وصف الحل
تحتاج أولاً إلى تحديد الحد الأدنى من المعلومات اللازمة لاتخاذ قرار بشأن عرض أحد المكونات. من الواضح ، من أجل العرض ، من الضروري استيفاء بعض الشروط (كخيار ، هناك نوع من الحق - على سبيل المثال ، الحق في إضافة مستخدم جديد). نسمي هذا الشرط
متطلبًا (أو متطلبًا باللغة الإنجليزية). لفهم ما إذا كان الشرط قد تم استيفاؤه ، يمكننا استنادًا إلى
مجموعة من حقوق المستخدم
الحالية -
بيانات الاعتماد . أي أنه يكفي تحديد وظيفة:
function isSatisfied(requirement, credentials) { if (...) { return false; } return true; }
الآن قررنا بشكل أو بآخر حالة العرض. كيفية استخدامه؟
1. يمكننا استخدام نهج الجبين:
const requirement = {...}; class App extends Component { render() { const {credentials} = this.props; return isSatisfied(requirement, credentials) && <TargetComponent>; } }
2. يمكننا أن نذهب إلى أبعد من ذلك قليلاً ، ونلف العنصر المستهدف في عنصر آخر ، مما سيؤدي إلى التحقق من المتطلبات:
const requirement = {...}; class ProtectedTargetComponent extends Component { render() { const {credentials} = this.props; return ( isSatisfied(requirement, credentials) ? <TargetComponent {...this.props}> {this.props.children} </TargetComponent> : null ); } } class App extends Component { render() { const {credentials} = this.props; return <ProtectedTargetComponent/>; } }
إن كتابة غلاف لكل مكون هدف يدويًا أمر كئيب جدًا. كيف يمكننا تبسيط هذا؟
3. يمكننا اللجوء إلى آلية HOC (عن طريق القياس مع الاتصال من "رد فعل-رد-ربط"):
function protect(requirement, WrappedComponent) { return class extends Component { render() { const { credentials } = this.props; return ( isSatisfied(requirement, credentials) ? <WrappedComponent {...this.props}> {this.props.children} </WrappedComponent> : null ); } } } ... const requireAdmin = {...}; const AdminButton = protect(requireAdmin, Button); ... class App extends Component { render() { const {credentials} = this.props; return ( ... <AdminButton credentials={credentials}> Add user </AdminButton> ... ); } }
أفضل بالفعل ، ولكن لا يزال بائسًا - تحتاج إلى إلقاء أوراق الاعتماد يدويًا من خلال شجرة المكونات بالكامل. ما الذي يمكن عمله بهذا؟ من المنطقي أن نفترض أن بيانات اعتماد المستخدم الحالي هي كائن عام للتطبيق بأكمله. ثم مرة أخرى يأتي رد الفعل-رد الاتصال لإنقاذ. بعد قراءة مقال حول جهاز هذه الوحدة ، نجد أنها تستخدم بعض
سياقات ReactJS.
4. باستخدام آلية السياق ، نحصل على النهج النهائي:
const { Provider, Consumer } = React.createContext(); function protect(requirement, WrappedComponent) { return class extends Component { render() { return ( <Consumer> { credentials => isSatisfied(requirement, credentials) ? <WrappedComponent {...this.props}> {this.props.children} </WrappedComponent> : null } </Consumer> ); } } } ... const requireAdmin = {...}; const AdminButton = protect(requireAdmin, Button); ... class App extends Component { render() { const { credentials } = this.props; return ( <Provider value={credentials}> ... <AdminButton> Add user </AdminButton> ... </Provider> ); } }
خاتمة
لقد كان انحرافًا موجزًا في الفكرة نفسها. استنادًا إلى هذه الفكرة ، تم تنفيذ وحدة (
github ،
npm ) ، والتي توفر ميزات أكثر إثارة للاهتمام وأسهل للتضمين (راجع README.md في github والعروض
التوضيحية باستخدام الوحدة النمطية).
لسبب ما فقط ، لم أتمكن من الحصول على حزمة npm التي تم إنشاؤها في العرض التوضيحي ، لذلك اضطررت إلى إدخال رمز الوحدة النمطية هناك. لكن الوحدة المثبتة من خلال
npm install response-rbac-guard تعمل محليًا (Chrome 69.0.3497.100). أظن أن المشكلة تكمن في طريقة البناء - لقد قمت للتو بنسخ ملفات package.json و webpack.config.prod.js من
وحدة نمطية لغرض مشابه.
نظرًا لأنني لست مطورًا أماميًا ، فلا يزال هناك الكثير من العمل غير المكتمل (نقص الاختبارات وعدم قابلية التشغيل في
https://codesandbox.io وربما نقاط أخرى ضائعة). لذلك ، إذا كانت هناك تعليقات أو اقتراحات أو طلبات سحب ، فمرحباً بك!
PPS: جميع التعليقات بخصوص الإملاء ، بما في ذلك في README.md ، يرجى إرسال رسائل شخصية أو في شكل طلب سحب.