Loại proptype chính xác cho một ref trong React là gì?


85

Tôi đang lưu trữ một ref trong cửa hàng redux của mình và sử dụng mapStateToProps để hiển thị ref cho các thành phần cần truy cập vào nó.

Tham chiếu được lưu trữ trông giống như:

ref={node => this.myRefToBePutInReduxGlobalStore = node}

PropType chính xác cho ref này là gì?


8
Vì refs không thể được serializable, nên bạn không nên đưa chúng vào cửa hàng Redux. Tuy nhiên, giá trị được truyền cho refprop là một hàm có đối số đầu tiên là tham chiếu đến phần tử DOM hoặc null. Đó là một chức năng .
rishat

5
Bạn không thể sử dụng propType cho refs, nhưng bạn có thể sử dụng nó cho props. Vì bạn đang chuyển nó đến cửa hàng redux nên nó được biểu thị dưới dạng proptương tự this.props.myRefToBePutInReduxGlobalStore. myRefToBePutInReduxGlobalStorephải là loại nút, vì vậy PropTypes.nodesẽ phù hợp với bạn
The Reason

Tôi nghĩ điều đó nên xảy ra PropType.objectbởi vì ref về cơ bản là cá thể lớp là đối tượng. Do đó khi bạn vượt qua yếu tố ref như một đạo cụ nó sẽ là của đối tượng loại
Hriday Modi

Câu trả lời:


96

TL; DR

Nếu bạn muốn gõ một tham chiếu chỉ yêu cầu các phần tử DOM gốc, chẳng hạn như a divhoặc an input, thì định nghĩa đúng là như sau:

refProp: PropTypes.oneOfType([
    // Either a function
    PropTypes.func, 
    // Or the instance of a DOM native element (see the note about SSR)
    PropTypes.shape({ current: PropTypes.instanceOf(Element) })
])

Câu trả lời cho vấn đề cụ thể được mô tả trong bài đăng gốc

Trong ví dụ của câu hỏi OP, nó không phải là kiểu ref prop cần được khai báo, mà là thứ được trỏ bởi ref và sẽ được chuyển từ redux bằng cách sử dụng mapStateToProps. Loại đề xuất cho phần tử DOM sẽ là: myRefToBePutInReduxGlobalStore: PropTypes.instanceOf(Element)(nếu đó là phần tử DOM). Mặc dù, tôi sẽ:

  1. Đổi tên nó thành myElementToBePutInReduxGlobalStore(một phần tử không phải là một ref)
  2. Tránh lưu trữ dữ liệu không thể tuần tự hóa bên trong cửa hàng redux
  3. Tránh chuyển các phần tử trong đạo cụ theo giải thích của kỹ sư React Seb Markbage

Câu trả lời dài cho câu hỏi thực tế

Q: Đâu là loại proptype chính xác cho một ref trong React?

Trường hợp sử dụng ví dụ:

function FancyInput({ inputRef }) {
    return (
        <div className="fancy">
            Fancy input
            <input ref={inputRef} />
        </div>
    )
}

FancyInput.propTypes = {
    inputRef: ???   // What is the correct prop type here?
}

function App(props) {
    const inputRef = React.useRef()
    useLayoutEffect(function focusWhenStuffChange() {
        inputRef.current?.focus()
    }, [props.stuff])
    return <FancyInput inputRef={inputRef} />
}

Ngày nay, có hai loại refs tồn tại trong phản ứng:

  1. Một đối tượng trông như thế này { current: [something] }:, thường được tạo bởi React.createRef()helper hoặc React.useRef()hook
  2. Một hàm gọi lại sẽ nhận [something]làm đối số của nó (giống như trong ví dụ OP)

Lưu ý: về mặt lịch sử, bạn cũng có thể sử dụng một tham chiếu chuỗi, nhưng nó được coi là kế thừa và sẽ bị xóa khỏi phản ứng

Mục thứ hai là khá đơn giản và đòi hỏi loại prop sau: PropTypes.func.

Tùy chọn đầu tiên ít rõ ràng hơn vì bạn có thể muốn chỉ định loại phần tử được trỏ bởi ref.

Nhiều câu trả lời hay

ref có thể trỏ đến một cái gì đó khác ngoài phần tử DOM.

Nếu bạn muốn hoàn toàn linh hoạt:

refProp: PropTypes.oneOfType([
    PropTypes.func, 
    PropTypes.shape({ current: PropTypes.any })
])

Ở trên chỉ thực thi hình dạng của đối tượng ref w / currentproperty. Nó sẽ hoạt động mọi lúc cho bất kỳ loại ref nào. Đối với mục đích sử dụng kiểu chống đỡ, là một cách để phát hiện bất kỳ sự mâu thuẫn nào khi bạn phát triển , điều này có lẽ là đủ. Có vẻ như rất khó xảy ra rằng một đối tượng có hình dạng { current: [any] }, và được chuyển đến một giá refToForwardđỡ, sẽ không phải là một tham chiếu thực tế.

Tuy nhiên , bạn có thể muốn khai báo rằng thành phần của bạn không mong đợi bất kỳ loại tham chiếu nào, mà chỉ một loại nhất định, dựa trên những gì nó cần tham chiếu đó.

Tôi đã thiết lập một hộp cát trưng bày một số cách khác nhau để khai báo một số tham chiếu, thậm chí một số cách không theo quy ước, và sau đó thử nghiệm chúng với nhiều loại chống đỡ. Bạn có thể tìm thấy nó ở đây .


Nếu bạn chỉ mong đợi một tham chiếu trỏ đến một phần tử đầu vào gốc, không phải bất kỳ HTML nàoElement :

refProp: PropTypes.oneOfType([
    PropTypes.func, 
    PropTypes.shape({ current: PropTypes.instanceOf(HTMLInputElement) })
])

Nếu bạn chỉ mong đợi một tham chiếu trỏ đến một thành phần lớp React:

refProp: PropTypes.oneOfType([
    PropTypes.func, 
    PropTypes.shape({ current: PropTypes.instanceOf(Component) })
])

Nếu bạn chỉ mong đợi một tham chiếu trỏ đến một thành phần chức năng sử dụng useImperativeHandleđể hiển thị một số phương thức công khai:

refProp: PropTypes.oneOfType([
    PropTypes.func, 
    PropTypes.shape({ current: PropTypes.object })
])

Lưu ý: kiểu prop ở trên rất thú vị vì nó cũng bao gồm các thành phần phản ứng và các phần tử DOM gốc, vì tất cả chúng đều kế thừa javascript cơ sở Object


Không có cách nào tốt để khai báo kiểu chống đỡ cho một ref, nó phụ thuộc vào cách sử dụng. Nếu giới thiệu của bạn trỏ đến một cái gì đó rất được xác định, bạn có thể thêm một loại hỗ trợ cụ thể. Nếu không, chỉ cần kiểm tra hình dạng chung là đủ.


Lưu ý về kết xuất phía máy chủ

Nếu mã của bạn phải chạy trên máy chủ, trừ khi bạn đã polyfill DOM môi trường Elementhoặc bất kỳ loại phía máy khách nào khác sẽ undefinedở trong NodeJS. Bạn có thể sử dụng miếng đệm sau để hỗ trợ nó:

Element = typeof Element === 'undefined' ? function(){} : Element

Các trang React Docs sau đây cung cấp thông tin chi tiết hơn về cách sử dụng refs, cả object và callback cũng như cách sử dụng useRefhook

Đã cập nhật câu trả lời, cảm ơn @Rahul Sagore, @Ferenk Kamra, @svnm và @Kamuela Franco


2
Nó cung cấp Elementkhông được xác định trên kết xuất phía máy chủ. Bất kỳ giải pháp cho điều đó?
Rahul Sagore

Điểm tốt. Còn về miếng đệm này thì sao: Element = typeof Element === 'undefined' ? function(){} : Element(do Ryan Florence gợi ý trong một số vấn đề trên github). Nếu nó phù hợp với bạn, tôi có thể thêm nó vào câu trả lời của mình.
Pandaiolo

Tôi đã tìm ra nó và thêm điều này if (!isBrowser) { global.Element = null; }. Đã làm cho tôi. isBrowser = typeof window !== 'undefined';
Rahul Sagore

Câu trả lời chính xác. Tôi rất thích TL; DR đứng đầu phản hồi.
Kamuela Franco

12

Rất giống với bài đăng của @ Pandaiolo,

PropTypes.elementType bây giờ đã được thêm vào

forwardedRef: PropTypes.oneOfType([
  PropTypes.func,
  PropTypes.shape({ current: PropTypes.elementType })
]),

Nếu sử dụng PropTypes> = 15.7.0 PropTypes.elementTypeđã được thêm vào ngày 10 tháng 2 năm 2019 trong PR này


Cảm ơn @svnm, tôi đã cập nhật câu trả lời của mình để phản ánh điều này, giúp nó đơn giản hơn!
Pandaiolo

1
Cuối cùng, điều đó elementTypekhông hiệu quả với tôi, vì vậy tôi thực sự đã thử nghiệm một loạt các loại chân đế trên các loại thành phần khác nhau có thể được chỉ bởi một ref, trong một hộp cát. Đây là kết quả: Codeandbox.io/s/loving-benz-w6fbh . Tôi không chắc mình đã đề cập đến tất cả các khả năng, nhưng có vẻ như proptype chính xác cho phần tử DOM là instanceOf(Element)(hoặc object), đối với một lớp thì nó là instanceOf(Component)(hoặc object) và cho trường hợp sử dụng cụ thể của một thành phần chức năng sử dụng useImperativeHandleobject. Suy nghĩ?
Pandaiolo

9

Tôi chỉ kiểm tra cách ưa thích và vì PropType.object không có giá trị lắm nên tôi đã sử dụng cách này:

PropTypes.shape({ current: PropTypes.instanceOf(Element) })

1

Tôi đã kiểm tra tất cả các câu trả lời trên nhưng tôi nhận được cảnh báo từ phản ứng, vì vậy tôi đã nghiên cứu rất nhiều và tôi đã có câu trả lời đúng.

import React, { Component } from 'react';

ComponentName.propTypes = {
  reference: PropTypes.oneOfType([
    PropTypes.func,
    PropTypes.shape({ current: PropTypes.instanceOf(Component) }),
  ]),
};
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.