Konversi data GraphQL untuk komponen CustomTreeData dari DevExtreme-Reactive

Dibutuhkan di sini untuk menampilkan data dalam bentuk pohon, dengan kemampuan untuk mengedit bidang yang berbeda, menghapus / menambah baris, dll. Dalam proses mencari komponen yang sesuai (saya ingin mencari di bawah material-ui dan bereaksi), saya mulai mencoba devextreme-reaktif . Namun, Newans menemukan bahwa devextreme-reactive menginginkan data untuk tree sebagai susunan objek yang datar, yang masing-masing berisi parent_id dari β€œparent”. Server GraphQL memberi saya pohon dalam bentuk objek bersarang dengan array objek. Saya harus melakukan yang lain dari satu - mungkin seseorang akan berguna. Atau mungkin seseorang akan mengatakan bahwa saya tidak bingung dengan kasus ini, dan semua ini dilakukan dengan lebih mudah.

Jadi, dalam menanggapi permintaan GraphQL (ada tes, masing-masing memiliki pertanyaan, untuk setiap survei ada beberapa pilihan jawaban dan kami ingin mendapatkan semuanya sekaligus):

query TestQuery { tests { id title questions { id title answers { id title } } } } 

Kami mendapat respons dari server dari formulir:

Judul spoiler
 { "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": [] } ] } } 


Untuk menormalkan, gunakan normalizr :

Dalam deskripsi skema, melalui processStrategy, kami menambahkan properti pid ke anak-anak dengan tautan ke orang tua. By the way, dalam normalizr baru, cara menggambarkan sirkuit telah berubah, karena contoh-contoh dengan assignEntity, ArrayOf, mendefinisikan (yang banyak) hampir tidak relevan.

 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]}) 

Kami mendapatkan ini:

Judul spoiler
 { "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" ] } } 


Dari sini kami hanya tertarik pada .entities

 const normalized = { entities: nRes.entities } 

Ngomong-ngomong, dalam proses memasuki normalizr, setelah membacakan masalah, saya menemukan bahwa saya bukan satu-satunya yang mencoba menggunakannya bukan untuk tujuan yang dimaksudkan (mungkin hanya karena itu hampir satu-satunya alat seperti itu). Banyak orang mendambakan segala macam fitur untuk mendapatkan hasil dalam format yang paling dapat disesuaikan. Tetapi penulis batu.

Dalam pandangan di atas, hasil normalizr harus diratakan menggunakan flat (kami secara rekursif memperluas ke tingkat yang diinginkan bersarang):

 const flattened = flatten({ entities: nRes.entities }, { maxDepth: 3 }) 

Kami mendapatkan yang berikut ini:

Judul spoiler
 { "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 } } 


Menyingkirkan indeks:

 Object.keys(flattened).forEach( (key)=> rows.push(flattened[key]) ) 

Kami mendapatkan:

Judul spoiler
 [ { "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 } ] 


Dimungkinkan untuk membersihkan array pertanyaan yang tersisa, jawaban yang tersisa di sini, tetapi ini adalah hal sepele - mereka tidak mempengaruhi tampilan. Dan __typename diperlukan agar nanti saat mengedit kita mengerti apa yang sedang kita hadapi.

Dalam komponen, hasilnya diproses seperti yang ditunjukkan dalam contoh mereka:

 ... <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 } ... 

Tampaknya alternatif untuk semua hal di atas mungkin dengan membaca langsung isi toko GraphQL (di klien Apollo) - semuanya juga harus datar di sana. Tetapi, jujur ​​saja, saya tidak menemukan bagaimana hal ini dapat dilakukan dengan cara standar, dan saya tidak begitu yakin bahwa format penyimpanan data di sana tidak akan berubah dalam versi baru.

Source: https://habr.com/ru/post/id416111/


All Articles