Cara menggunakan forwardRef dengan FunctionComponent di React Native menggunakan TypeScript

Oct 22 2020

Saya telah melihat banyak dokumen dan contoh tetapi saya masih belum cukup memahami bagaimana menggunakan forwardRefkomponen fungsional dengan TypeScript di React Native. Di bawah ini adalah contoh di mana saya membuat MyCustomComponentdengan fungsi kustom yang saya coba panggil dari orang tua dengan membuat ref. Namun, karena ref tidak didefinisikan dengan benar dan null, saya jelas mendapatkan pesan kesalahan yang memberi tahu saya bahwa fungsinya tidak ada. Tolong bantu saya memahami bagaimana menggunakan dengan benar forwardRefdi React Native. Terima kasih sebelumnya!

interface MyCustomComponentProps {
    title: string
}

const MyCustomComponent: React.FunctionComponent<MyCustomComponentProps> = React.forwardRef((props, ref) => {
    const coolAlert = () => {
        Alert.alert('Hey!', 'This was called from MyCustomComponent')
    }
    return (
        <View>
            <Text>{props.title}</Text>
        </View>
    )
})

export default function App () {
    const MyCustomComponentRef = useRef()
    return (
        <SafeAreaView>
            <MyCustomComponent ref={MyCustomComponentRef} title='Hello World' />
            <TouchableOpacity
                onPress={() => {
                    MyCustomComponentRef.coolAlert()
                }}>
                <Text>Click Me</Text>
            </TouchableOpacity>
        </SafeAreaView>
    )
}

Jawaban

3 LindaPaiste Oct 22 2020 at 23:27

Meneruskan Ref

Ref bisa sangat membingungkan karena ada banyak cara untuk menanganinya dan karena orang tidak menyadari perbedaan antara objek ref ( React.MutableRefObjectatau React.RefObject) dan nilai ref, yang disimpan di .currentproperti objek ref. Anda telah membuat kesalahan itu di sini, bersama dengan beberapa jenis skrip yang hilang atau salah.

useRef<T>adalah pengait umum di mana nilainya Tmenjelaskan jenis nilai apa yang akan disimpan. Kita perlu memberi tahu Appbahwa kita bermaksud menyimpan sesuatu dengan suatu coolAlertmetode. Sebenarnya kita akan lihat nanti bahwa kita membutuhkan ref kita untuk menjadi tidak berubah jadi kita akan menggunakan createRef<T>sebagai gantinya.

interface MyRef {
  coolAlert(): void;
}

const MyCustomComponentRef = createRef<MyRef>();

Saat kita memanggil onPress, kita perlu mengakses nilai saat ini dari objek ref. Dengan menambahkan generik ke createRef, skrip ketikan sudah mengetahui bahwa nilai ini adalah MyRefatau undefined. Kami dapat menelepon coolAlertdengan ?.operator rantai opsional .

onPress={() => MyCustomComponentRef.current?.coolAlert()}

Sekarang kita perlu melakukan beberapa pekerjaan MyCustomComponent. Anda telah salah dengan menetapkan tipe React.FunctionComponent<MyCustomComponentProps>karena komponen fungsi tidak memiliki pengetahuan tentang penerusan ref yang kita butuhkan.

function forwardRef<T, P = {}>(Component: RefForwardingComponent<T, P>): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;

Jenis untuk MyCustomComponentharus dari jenis pengembalian rumit itu forwardRef. Tapi kita tidak perlu menetapkan tipe itu sendiri, kita hanya perlu meneruskan generik Tdan Pke forwardRefpemanggilan fungsi. Tadalah tipe ref dan Pmerupakan tipe props.

const MyCustomComponent = React.forwardRef<MyRef, MyCustomComponentProps>(...

Ok jadi kami menyingkirkan semua kesalahan skrip ketikan ! Yay! Kecuali ... tunggu. Itu sebenarnya tidak melakukan apa-apa . Semua itu dan masih belum berhasil. Saya benci ref. Referensi buruk.

Menggunakan Ref

Kami meneruskan referensi ke MyCustomComponent, yang sekarang memiliki akses ke referensi yang diteruskan dan dapat melampirkannya ke komponen DOM. Tapi kami tidak ingin itu dilampirkan ke elemen DOM, kami ingin itu dilampirkan MyCustomComponent. Tapi kita tidak bisa melakukan itu.

Secara default, Anda tidak boleh menggunakan atribut ref pada komponen fungsi karena tidak memiliki instance [docs]

Kami harus menggunakan hook yang disebut useImperativeHandleyang terasa seperti solusi hack dan bahkan dokumen mengatakan "jangan lakukan ini". Yup, saya benci ref.

useImperativeHandle menyesuaikan nilai instance yang diekspos ke komponen induk saat menggunakan ref. Seperti biasa, kode imperatif yang menggunakan ref harus dihindari dalam banyak kasus. useImperativeHandle harus digunakan dengan forwardRef. [dokumen]

Kami harus mengekspos coolAlertmetode kami useImperativeHandle.

useImperativeHandle(ref , () => ({coolAlert}));

Dan sekarang ini benar-benar berhasil , akhirnya!