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.