استغرق الأمر هنا لعرض البيانات في شكل شجرة ، مع القدرة على تحرير الحقول المختلفة ، وحذف / إضافة صفوف ، وما إلى ذلك. في عملية البحث عن مكونات مناسبة (أردت أن أجد تحت
واجهة المستخدم المادية والتفاعل) بدأت في تجربة
تفاعل تفاعلي . ومع ذلك ، وجد نيانز أن التفاعل المتطرف يريد بيانات الشجرة كمجموعة مسطحة من الكائنات ، يحتوي كل منها على معرف_الوالد الخاص بـ "الأصل". يمنحني خادم GraphQL شجرة على شكل كائنات متداخلة مع صفائف من الكائنات. كان علي أن أفعل الآخر من واحد - ربما شخص ما سيكون في متناول اليد. أو ربما سيقول أحدهم أنني لم أكن مرتبكًا بشأن القضية ، وكل هذا يتم بسهولة أكبر.
لذلك ، ردًا على استعلام GraphQL (هناك اختبارات ، لكل منها أسئلة ، لكل استطلاع هناك العديد من خيارات الإجابة ونريد الحصول على كل شيء دفعة واحدة):
query TestQuery { tests { id title questions { id title answers { id title } } } }
نحصل على رد من خادم النموذج:
عنوان المفسد { "data": { "tests": [ { "id": "test_1", "title": "Test 1", "questions": [ { "id": "question_1", "title": "Question 1 (for t1)", "answers": [ { "id": "answer_1", "title": "Answer 1 (for q1)" }, { "id": "answer_2", "title": "Answer 2 (for q1)" } ] }, { "id": "question_2", "title": "Question 2 (for t1)", "answers": [ { "id": "answer_1_2", "title": "Answer 1 (for q2)" } ] } ] }, { "id": "test_2", "title": "Test 2", "questions": [ { "id": "question_1_2", "title": "Question 1 (for t2)", "answers": [] } ] }, { "id": "test_3", "title": "Test 3", "questions": [] } ] } }
للتطبيع ، استخدم
normalizr :
في وصف المخطط ، من خلال عملية الإستراتيجية ، نضيف خصائص pid للأطفال الذين لديهم روابط لأولياء الأمور. بالمناسبة ، في الوضع الطبيعي الجديد ، تغيرت طريقة وصف الدوائر ، والتي من أجلها تكون الأمثلة مع تعيينEntity ، ArrayOf ، تعريف (وهي كثيرة) غير ذات صلة تقريبًا.
const answerSchema = new schema.Entity('answers',{}, { processStrategy: (entity, parent, key) => { return { ...entity, pid: parent.id} } } ) const questionSchema = new schema.Entity('questions',{ answers:[answerSchema]}, { processStrategy: (entity, parent, key) => { return { ...entity, pid: parent.id} } }, ) const testSchema = new schema.Entity('tests',{questions:[questionSchema]}, { processStrategy: (entity, parent, key) => { return { ...entity, pid: 0 } } } ) const nRes = normalize(result.data, {tests: [testSchema]})
نحصل على هذا:
عنوان المفسد { "entities": { "answers": { "answer_1": { "id": "answer_1", "title": "Answer 1 (for q1)", "__typename": "Answer", "pid": "question_1" }, "answer_2": { "id": "answer_2", "title": "Answer 2 (for q1)", "__typename": "Answer", "pid": "question_1" }, "answer_1_2": { "id": "answer_1_2", "title": "Answer 1 (for q2)", "__typename": "Answer", "pid": "question_2" } }, "questions": { "question_1": { "id": "question_1", "title": "Question 1 (for t1)", "answers": [ "answer_1", "answer_2" ], "__typename": "Question", "pid": "test_1" }, "question_2": { "id": "question_2", "title": "Question 2 (for t1)", "answers": [ "answer_1_2" ], "__typename": "Question", "pid": "test_1" }, "question_1_2": { "id": "question_1_2", "title": "Question 1 (for t2)", "answers": [ ], "__typename": "Question", "pid": "test_2" } }, "tests": { "test_1": { "id": "test_1", "title": "Test 1", "questions": [ "question_1", "question_2" ], "__typename": "Test", "pid": 0 }, "test_2": { "id": "test_2", "title": "Test 2", "questions": [ "question_1_2" ], "__typename": "Test", "pid": 0 }, "test_3": { "id": "test_3", "title": "Test 3", "questions": [ ], "__typename": "Test", "pid": 0 } } }, "result": { "tests": [ "test_1", "test_2", "test_3" ] } }
من هنا نحن مهتمون فقط بالميثاق
const normalized = { entities: nRes.entities }
بالمناسبة ، في عملية الدخول إلى normalizr ، بعد قراءة القضايا ، اكتشفت أنني لست الوحيد الذي يحاول استخدامه ليس للغرض المقصود (ربما لمجرد أنه الأداة الوحيدة تقريبًا). يتوق العديد من الأشخاص إلى جميع أنواع الميزات من أجل الحصول على النتيجة بالتنسيق الأكثر تخصيصًا. لكن المؤلفين فلينت.
في ضوء ما سبق ، يجب تسوية نتيجة Normalizr باستخدام
مسطح (نتوسع بشكل متكرر إلى المستوى المطلوب من التعشيش):
const flattened = flatten({ entities: nRes.entities }, { maxDepth: 3 })
نحصل على ما يلي:
عنوان المفسد { "entities.answers.answer_1": { "id": "answer_1", "title": "Answer 1 (for q1)", "__typename": "Answer", "pid": "question_1" }, "entities.answers.answer_2": { "id": "answer_2", "title": "Answer 2 (for q1)", "__typename": "Answer", "pid": "question_1" }, "entities.answers.answer_1_2": { "id": "answer_1_2", "title": "Answer 1 (for q2)", "__typename": "Answer", "pid": "question_2" }, "entities.questions.question_1": { "id": "question_1", "title": "Question 1 (for t1)", "answers": [ "answer_1", "answer_2" ], "__typename": "Question", "pid": "test_1" }, "entities.questions.question_2": { "id": "question_2", "title": "Question 2 (for t1)", "answers": [ "answer_1_2" ], "__typename": "Question", "pid": "test_1" }, "entities.questions.question_1_2": { "id": "question_1_2", "title": "Question 1 (for t2)", "answers": [ ], "__typename": "Question", "pid": "test_2" }, "entities.tests.test_1": { "id": "test_1", "title": "Test 1", "questions": [ "question_1", "question_2" ], "__typename": "Test", "pid": 0 }, "entities.tests.test_2": { "id": "test_2", "title": "Test 2", "questions": [ "question_1_2" ], "__typename": "Test", "pid": 0 }, "entities.tests.test_3": { "id": "test_3", "title": "Test 3", "questions": [ ], "__typename": "Test", "pid": 0 } }
التخلص من المؤشرات:
Object.keys(flattened).forEach( (key)=> rows.push(flattened[key]) )
نحصل على:
عنوان المفسد [ { "id": "answer_1", "title": "Answer 1 (for q1)", "__typename": "Answer", "pid": "question_1" }, { "id": "answer_2", "title": "Answer 2 (for q1)", "__typename": "Answer", "pid": "question_1" }, { "id": "answer_1_2", "title": "Answer 1 (for q2)", "__typename": "Answer", "pid": "question_2" }, { "id": "question_1", "title": "Question 1 (for t1)", "answers": [ "answer_1", "answer_2" ], "__typename": "Question", "pid": "test_1" }, { "id": "question_2", "title": "Question 2 (for t1)", "answers": [ "answer_1_2" ], "__typename": "Question", "pid": "test_1" }, { "id": "question_1_2", "title": "Question 1 (for t2)", "answers": [ ], "__typename": "Question", "pid": "test_2" }, { "id": "test_1", "title": "Test 1", "questions": [ "question_1", "question_2" ], "__typename": "Test", "pid": 0 }, { "id": "test_2", "title": "Test 2", "questions": [ "question_1_2" ], "__typename": "Test", "pid": 0 }, { "id": "test_3", "title": "Test 3", "questions": [ ], "__typename": "Test", "pid": 0 } ]
سيكون من الممكن تنظيف مصفوفات الأسئلة المتبقية ، والإجابات المتبقية هنا ، ولكن هذه تفاهات - فهي لا تؤثر على الشاشة. وهناك حاجة إلى __typename حتى نفهم فيما نتعامل معه عند التحرير.
في المكون ، تتم معالجة النتيجة كما هو موضح في
مثالهم :
... <CustomTreeData getChildRows={getChildRows} /> ... const getChildRows = (currentRow, rootRows) => { const childRows = rootRows.filter(r => r.pid === (currentRow ? currentRow.id : 0)); const res = childRows.length ? childRows : null return res } ...
يبدو أن البديل لكل ما سبق قد يكمن في قراءة محتويات متجر GraphQL مباشرة (في عميل Apollo) -
يجب أن يكون كل شيء مسطحًا هناك. ولكن ، بصراحة ، لم أجد كيف يمكن القيام بذلك بطريقة قياسية ، ولست متأكدًا تمامًا من أن التنسيق الذي يتم فيه تخزين البيانات هناك لن يتغير في الإصدارات الجديدة.