วิธีใช้ forwardRef กับ FunctionComponent ใน React Native โดยใช้ TypeScript
ฉันได้ดูเอกสารและตัวอย่างมากมายแล้ว แต่ดูเหมือนว่าฉันยังไม่เข้าใจวิธีใช้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>
)
}
คำตอบ
การส่งต่อ 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}));
และตอนนี้ก็ใช้งานได้จริงในที่สุด!