Cách sử dụng forwardRef với FunctionComponent trong React Native bằng TypeScript

Oct 22 2020

Tôi đã xem qua nhiều tài liệu và ví dụ nhưng dường như tôi vẫn không thể hiểu rõ cách sử dụng forwardRefvới một thành phần chức năng với TypeScript trong React Native. Dưới đây là một ví dụ mà tôi tạo một MyCustomComponentvới một hàm tùy chỉnh mà tôi cố gắng gọi từ cấp độ gốc bằng cách tạo một tham chiếu. Tuy nhiên, vì ref được xác định không chính xác và null, tôi rõ ràng nhận được thông báo lỗi cho tôi biết rằng hàm không tồn tại. Vui lòng giúp tôi hiểu cách sử dụng đúng cách forwardReftrong React Native. Cảm ơn trước!

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

Trả lời

3 LindaPaiste Oct 22 2020 at 23:27

Chuyển tiếp Ref

Refs có thể thực sự gây nhầm lẫn vì có nhiều cách để xử lý chúng và bởi vì mọi người không nhận thức được sự khác biệt giữa đối tượng ref ( React.MutableRefObjecthoặc React.RefObject) và giá trị ref, được lưu trữ trên thuộc .currenttính của đối tượng ref. Bạn đã mắc lỗi đó ở đây, cùng với một số loại bảng chữ bị thiếu hoặc không chính xác.

useRef<T>là một hook chung trong đó giá trị Tcho biết loại giá trị nào sẽ được lưu trữ. Chúng ta cần phải nói Apprằng chúng ta dự định lưu trữ một cái gì đó bằng một coolAlertphương thức. Trên thực tế, sau này chúng ta sẽ thấy rằng chúng ta cần ref của mình là không thể thay đổi nên chúng ta sẽ sử dụng createRef<T>thay thế.

interface MyRef {
  coolAlert(): void;
}

const MyCustomComponentRef = createRef<MyRef>();

Khi chúng ta gọi onPress, chúng ta cần truy cập giá trị hiện tại của đối tượng ref. Bằng cách thêm giá trị chung vào createRef, chỉ định kiểu đã biết rằng giá trị này là MyRefhoặc undefined. Chúng tôi có thể gọi coolAlertvới ?.nhà điều hành chuỗi tùy chọn .

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

Bây giờ chúng ta cần làm một số công việc MyCustomComponent. Bạn đã sai khi gán loại cho nó React.FunctionComponent<MyCustomComponentProps>vì một thành phần hàm không có kiến ​​thức về chuyển tiếp ref mà chúng ta cần.

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

Loại for MyCustomComponentphải là loại trả về phức tạp từ forwardRef. Nhưng chúng ta không cần phải tự gán kiểu đó, chúng ta chỉ cần chuyển generics Tvà Pcho forwardReflời gọi hàm. Tlà loại giới thiệu và Plà loại đạo cụ.

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

Ok, vậy là chúng ta đã loại bỏ được tất cả các lỗi sắp chữ ! Yay! Ngoại trừ ... giữ máy. Nó không thực sự làm bất cứ điều gì . Tất cả những điều đó và nó vẫn không hoạt động. Tôi ghét refs. Refs tệ.

Sử dụng Ref

Chúng tôi đã chuyển tiếp ref tới MyCustomComponent, người hiện có quyền truy cập vào ref được chuyển tiếp và có thể đính kèm nó vào thành phần DOM. Nhưng chúng tôi không muốn nó được gắn vào phần tử DOM, chúng tôi muốn nó được gắn vào MyCustomComponent. Nhưng chúng tôi thực sự không thể làm điều đó.

Theo mặc định, bạn không thể sử dụng thuộc tính ref trên các thành phần hàm vì chúng không có phiên bản [docs]

Chúng tôi phải sử dụng một hook có tên gọi useImperativeHandlegiống như một giải pháp hack và thậm chí các tài liệu nói rằng "đừng làm điều này". Yup, tôi ghét refs.

useImperativeHandle tùy chỉnh giá trị cá thể được hiển thị với các thành phần mẹ khi sử dụng ref. Như mọi khi, mã bắt buộc sử dụng refs nên tránh trong hầu hết các trường hợp. useImperativeHandle nên được sử dụng với forwardRef. [tài liệu]

Chúng tôi phải để lộ coolAlertphương pháp của chúng tôi thông qua useImperativeHandle.

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

Và bây giờ nó thực sự hoạt động , cuối cùng!