React: Mengkloning anak konteks Konsumen menghasilkan peringatan dan kesalahan yang membingungkan

Dibuat pada 25 Apr 2018  ·  4Komentar  ·  Sumber: facebook/react

Apakah Anda ingin meminta fitur atau melaporkan bug ?
ini adalah bug, atau setidaknya permintaan untuk peringatan dan pesan kesalahan yang lebih tepat.

Bagaimana perilaku saat ini?

Saya mengkloning anak-anak untuk menambahkan beberapa properti dan saya mengabaikan bahwa konteks subpohon Konsumen tidak boleh dikloning ...

import React from 'react';
import {render} from 'react-dom';

const { Provider, Consumer} = React.createContext();

const Comp = ({children})=> <Provider>{cloneKids(children)}</Provider>;

const cloneKids=(children)=>React.Children.map(children, child =>
                           React.cloneElement(child, child.props,
                                  child.props.children&&
                                  cloneKids(child.props.children)));
render(
    <Comp><Consumer>{console.log}</Consumer></Comp>,
    document.getElementById('root')
);

Kode menghasilkan peringatan dan kesalahan yang diperkenalkan dengan # 12241

Peringatan: Konsumen konteks dirender dengan beberapa turunan, atau turunan yang bukan merupakan fungsi. Konsumen konteks mengharapkan satu anak yang merupakan fungsi. Jika Anda meneruskan suatu fungsi, pastikan tidak ada spasi kosong di belakangnya.

dan (bahkan lebih membingungkan)

TypeError: render bukanlah sebuah fungsi

Apa perilaku yang diharapkan?

Mungkin React.cloneElement seharusnya tidak mencoba mengkloning fungsi? Apapun yang dilakukannya, hasilnya bukanlah sebuah fungsi.

Bagian peringatan "anak yang bukan fungsi" harus dipisahkan dari peringatan lainnya. Tidak boleh ada banyak anak dan satu anak yang bukan merupakan fungsi pada saat yang sama, jadi peringatan yang lebih tepat dapat dikeluarkan.

Versi React mana, dan browser / OS mana yang terpengaruh oleh masalah ini?

Diuji dengan react 16.3.0 di Stackblitz / Chrome 65 dan react 16.3.2 di Chrome 65 dan Firefox 59

Question

Komentar yang paling membantu

Masalahnya bukan dengan cloneElement (tidak memiliki logika khusus untuk konteks), tetapi Anda meneruskan props.children (yang merupakan fungsi dalam kasus ini) ke Children.map() (yang tidak mengharapkan fungsi). Children.map hanya bekerja dengan node React biasa.

Mungkin Children.map dapat menampilkan peringatan ketika menemukan sesuatu yang bukan node React.

Dalam kasus mana pun, mengkloning pohon React secara mendalam seperti ini terdengar seperti Anda mencoba melakukan sesuatu yang tidak dirancang untuk React. Mengapa Anda membutuhkan ini?

Semua 4 komentar

Masalahnya bukan dengan cloneElement (tidak memiliki logika khusus untuk konteks), tetapi Anda meneruskan props.children (yang merupakan fungsi dalam kasus ini) ke Children.map() (yang tidak mengharapkan fungsi). Children.map hanya bekerja dengan node React biasa.

Mungkin Children.map dapat menampilkan peringatan ketika menemukan sesuatu yang bukan node React.

Dalam kasus mana pun, mengkloning pohon React secara mendalam seperti ini terdengar seperti Anda mencoba melakukan sesuatu yang tidak dirancang untuk React. Mengapa Anda membutuhkan ini?

Terima kasih!

Saya menunda evaluasi beberapa properti anak sampai orang tua siap memberikan konteks untuk evaluasi mereka. Sebagai contoh:

<Parent ><Child prefix-prop="string expression"></Parent>
(bahasa ekspresi bukan javascript dan dievaluasi dari jarak jauh. Saya tidak mengontrol Child, dan bisa ada sejumlah anak).

Anak itu secara internal menjadi seperti:

<Child prop={evaluate("string expression")} />

Untuk mencapai itu, orang tua mengunjungi anak-anak dan mengubah properti "prefix-prop" yang berisi ekspresi, menjadi properti "prop", yang berisi nilai ekspresi. Kloning adalah satu-satunya pendekatan yang saya temukan untuk mengubah properti komponen. Tentu saja konteks Konsumen tidak boleh dikloning, tidak ada properti yang dapat diubah di sana.

Saya tahu bahwa saya harus menggunakan function-as-child atau render functions atau serupa (untuk menunda evaluasi) tetapi saya merancang pustaka prototipe dan pengguna saya (yang berasal dari HTML dan JSP, dan seringkali pemula di luar HTML dan bahasa ekspresi) kemungkinan besar tidak akan menghargai notasi ini:

<Parent>{ context=> <Child prop={context.evaluate(x)} />}</Parent>

(selain itu, jika mereka lupa spasi sebelum fungsi tersebut, mereka akan bingung dengan # 12689)

dan mereka juga tidak akan segera memahami bentuk ini:
<Parent display={ context=> <Child prop={context.evaluate(x)} />} />

Konsumen konteks juga menggunakan function-as-child sehingga mereka memiliki masalah yang sama.

Ini adalah pekerjaan yang sangat awal jadi saya masih mempertimbangkan opsi, tetapi entah bagaimana saya ingin sampai pada notasi orang tua-anak yang bersih seperti di kutipan pertama. Mungkin saya harus menulis plugin babel yang mengubah notasi "bersih" menjadi yang fungsional.

Tapi mungkin saya melewatkan sesuatu jadi saya menghargai masukan apa pun. Saya sangat ingin pengguna saya meninggalkan JSP dan mengadopsi React tetapi jika notasinya terlalu samar, ini tidak akan terjadi ...

Ide lain yang saya mainkan adalah orang tua fungsional, mungkin mengembalikan Komponen (semacam HOC)

({context})=>
context.parent("context expression",
     context2=><Child prop={context2.evaluate("sub-expression")} context={context2} />)

di mana Child bisa berisi lagi panggilan context.parent (), dan seterusnya.

Tentu saja orang tua () bisa menggunakan konteks Konsumen dalam render () dari komponen yang dikembalikannya, sehingga prop konteks bisa dijatuhkan:

()=>
parent("context expression",
     context2=><Child prop={context2.evaluate("sub-expression")} />)

_ Masalahnya di sini adalah bahwa orang tua () sebagai Komponen dapat mengakses konteks React, tetapi evalu () tidak dapat (sepengetahuan saya) mengakses konteks React kecuali ia mengembalikan sebuah Komponen_

yang tidak mungkin dilakukan saat Anda benar-benar mencoba menyetel properti.

Oleh karena itu saya percaya bahwa mengakses konteks React dari komponen luar akan ideal. Sesuatu seperti

React.getContext(Consumer, data=> ...)

Jika saya ingat benar, ketika berjuang dengan ini, saya mencoba memanggil Consumer.render () secara manual menggunakan kerangka kerja pengujian, tetapi saya tidak mendapatkan sesuatu yang berarti.

PS: Notasi pertama di atas mungkin tampak samar tapi sebenarnya cukup familiar dengan bentuk JSP saat ini jadi saya rasa saya bisa menjualnya ke pengguna :)

<context:parent ctx="context-expression">
   HTML...<context:evaluate expr="sub-expression" />...HTML
</context:parent>

Mendekati karena ini sepertinya tidak sering muncul.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat