วิธีใช้ forwardRef กับ FunctionComponent ใน React Native โดยใช้ TypeScript

Oct 22 2020

ฉันได้ดูเอกสารและตัวอย่างมากมายแล้ว แต่ดูเหมือนว่าฉันยังไม่เข้าใจวิธีใช้forwardRefกับส่วนประกอบที่ใช้งานได้กับ TypeScript ใน React Native ด้านล่างนี้คือตัวอย่างที่ฉันสร้างMyCustomComponentด้วยฟังก์ชันที่กำหนดเองซึ่งฉันพยายามเรียกจากผู้ปกครองโดยสร้างการอ้างอิง อย่างไรก็ตามเนื่องจากการอ้างอิงถูกกำหนดไว้ไม่ถูกต้องและnullเห็นได้ชัดว่าฉันได้รับข้อความแสดงข้อผิดพลาดที่แจ้งว่าไม่มีฟังก์ชันนี้ โปรดช่วยฉันเข้าใจวิธีใช้forwardRefใน React Native อย่างถูกต้อง ขอบคุณล่วงหน้า!

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

คำตอบ

3 LindaPaiste Oct 22 2020 at 23:27

การส่งต่อ Ref

การอ้างอิงอาจสร้างความสับสนได้เนื่องจากมีหลายวิธีในการจัดการและเนื่องจากผู้คนไม่ทราบถึงความแตกต่างระหว่างวัตถุ ref ( React.MutableRefObjectหรือReact.RefObject) กับค่าการอ้างอิงซึ่งถูกเก็บไว้ใน.currentคุณสมบัติของวัตถุอ้างอิง คุณได้ทำผิดพลาดที่นี่พร้อมกับประเภทสคริปต์บางส่วนที่ขาดหายไปหรือไม่ถูกต้อง

useRef<T>เป็นตะขอทั่วไปที่ค่าTจะบอกประเภทของค่าที่จะจัดเก็บ เราจำเป็นต้องบอกAppว่าเราตั้งใจจะจัดเก็บบางอย่างด้วยcoolAlertวิธีการ ที่จริงเราจะเห็นในภายหลังว่าเราต้องการให้ ref ของเราไม่เปลี่ยนรูปดังนั้นเราจะใช้createRef<T>แทน

interface MyRef {
  coolAlert(): void;
}

const MyCustomComponentRef = createRef<MyRef>();

เมื่อเราเรียกonPressเราจำเป็นต้องเข้าถึงค่าปัจจุบันของวัตถุอ้างอิง โดยการเพิ่มทั่วไปcreateRef, typescript รู้อยู่แล้วว่าค่านี้เป็นอย่างใดอย่างหนึ่งหรือMyRef undefinedเราสามารถโทรติดต่อcoolAlertกับตัว?.ดำเนินการโซ่ที่เป็นทางเลือกได้

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

MyCustomComponentตอนนี้เราต้องทำผลงานบางอย่างเกี่ยวกับ คุณทำผิดโดยกำหนดประเภทReact.FunctionComponent<MyCustomComponentProps>เนื่องจากส่วนประกอบของฟังก์ชันไม่มีความรู้เกี่ยวกับการส่งต่ออ้างอิงที่เราต้องการ

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

ประเภทสำหรับ The ควรที่ซับซ้อนชนิดกลับจากMyCustomComponent forwardRefแต่เราไม่จำเป็นต้องกำหนดประเภทนั้นเองเราเพียงแค่ต้องส่งข้อมูลทั่วไปTและPไปยังการforwardRefเรียกใช้ฟังก์ชัน Tคือประเภทของการอ้างอิงและPเป็นประเภทของอุปกรณ์ประกอบฉาก

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

โอเคเราจึงกำจัดข้อผิดพลาด typescript ทั้งหมด ! เย้! ยกเว้น ... มันไม่ได้ทำอะไรจริง ทั้งหมดนั้นและยังไม่ได้ผล ฉันเกลียดการอ้างอิง การอ้างอิงไม่ดี

การใช้ Ref

เราส่งต่อการอ้างอิงไปยังMyCustomComponentซึ่งขณะนี้สามารถเข้าถึงการอ้างอิงที่ส่งต่อและสามารถแนบไปยังคอมโพเนนต์ DOM แต่เราไม่ต้องการให้มันแนบกับองค์ประกอบ DOM เราต้องการให้มันแนบไปMyCustomComponentด้วย แต่เราทำไม่ได้จริงๆ

โดยค่าเริ่มต้นคุณไม่สามารถใช้แอตทริบิวต์การหักล้างกับส่วนประกอบของฟังก์ชันได้เนื่องจากไม่มีอินสแตนซ์[docs]

เราต้องใช้ประโยชน์จาก hook useImperativeHandleที่ให้ความรู้สึกเหมือนเป็นวิธีการแฮ็กและแม้แต่เอกสารก็บอกว่า "อย่าทำ" ใช่ฉันเกลียดการอ้างอิง

useImperativeHandle ปรับแต่งค่าอินสแตนซ์ที่สัมผัสกับคอมโพเนนต์หลักเมื่อใช้การอ้างอิง เช่นเคยควรหลีกเลี่ยงรหัสที่จำเป็นโดยใช้การอ้างอิงในกรณีส่วนใหญ่ useImperativeHandle ควรใช้กับ forwardRef [เอกสาร]

เรามีที่จะเปิดเผยของเราวิธีการผ่านcoolAlertuseImperativeHandle

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

และตอนนี้ก็ใช้งานได้จริงในที่สุด!