2014-06-21 65 views
22

Tôi đang viết mã bằng CoffeeScript vì tôi đã viết React với nó.
Đây là cấu trúc cơ bản.ReactJS: Làm thế nào để truy cập vào refs của thành phần con?

{ div, input } = React.DOM 

Outer = React.createClass 
    render: -> 
    div { id: 'myApp' }, 
     Inner() 

Inner = React.createClass 
    render: -> 
    input { id: 'myInput', ref: 'myInput' } 

Tôi có một phương pháp toggle trên lớp Outer của tôi mà được kích hoạt bằng cách nhấn một phím tắt. Nó chuyển sang chế độ hiển thị của ứng dụng của tôi.
Khi ứng dụng của tôi được chuyển từ ẩn sang hiển thị, tôi muốn tập trung vào đầu vào.

Bây giờ các phương pháp chuyển đổi tìm kiếm nhiều hơn hoặc ít hơn như thế này:

Outer = React.createClass 
    render: -> 
    ...... 

    hide: -> 
    @setState { visible: no } 

    show: -> 
    @setState { visible: yes } 

    $('#myInput').focus() # jQuery 
    # I want to do something like 
    # @refs.myInput.getDOMNode().focus() 
    # But @refs here is empty, it doesn't contain the refs in Inner 

    toggle: -> 
    if @state.visible 
     @hide() 
    else 
     @show() 

Làm thế nào để làm được điều này sau đó?

Trả lời

25

Truy cập refs của một đứa trẻ ngắt đóng gói kể từ refs không được coi là một phần của API của thành phần. Thay vào đó bạn nên trưng ra một hàm trên Inner có thể được gọi bởi một thành phần cha, gọi nó là focus có thể có ý nghĩa.

Ngoài ra, tập trung phần tử trong componentDidUpdate để đảm bảo vẽ hoàn tất:

{ div, input } = React.DOM 

Outer = React.createClass 
    render: -> 
    div { id: 'myApp' }, 
     Inner({ref: 'inner'}) 

    componentDidUpdate: (prevProps, prevState) -> 
    # Focus if `visible` went from false to true 
    if (@state.visible && !prevState.visible) 
     @refs.inner.focus() 

    hide: -> 
    @setState { visible: no } 

    show: -> 
    @setState { visible: yes } 

    toggle: -> 
    if @state.visible 
     @hide() 
    else 
     @show() 

Inner = React.createClass 
    focus: -> 
    @refs.myInput.getDOMNode().focus() 

    render: -> 
    input { id: 'myInput', ref: 'myInput' } 
2

Trong trường hợp này giải pháp rất đơn giản, bạn có thể yêu cầu đầu vào tự động lấy nét, trong đó React tập trung nó khi nó được hiển thị.

Inner = React.createClass 
    render: -> 
    input { ref: 'myInput', autoFocus: true } 

Nói chung, bạn phải vượt qua một chỗ dựa để các thành phần bên trong, và trong componentDidUpdate bạn có thể làm:

if @props.something 
    @refs.myInput.getDOMNode().focus() 
+0

AutoFocus không làm việc cho tôi. Trên thực tế tôi chỉ nghĩ về 'componentDidUpdate' và thử một cái gì đó tương tự như những gì bạn đề nghị và nó làm việc. Nhưng tôi thực sự muốn biết liệu có một cách dễ dàng để truy cập vào refs của các thành phần con. Ví dụ refs trên React Doc đặt một đầu vào bên trong thành phần trên cùng, nhưng trên thực tế các đầu vào thường được lồng trong các thành phần con. – octref

+0

Chỉ có thể sử dụng các tham chiếu trong thành phần mà chúng được xác định. Nếu chúng có thể truy cập được bởi bất kỳ thành phần con nào, bạn phải giả sử tên của bạn cho một ref sẽ không đụng độ với bất kỳ ref nào khác. Bạn cũng sẽ phải kiểm tra mọi thành phần khác nếu bạn muốn loại bỏ một ref, hoặc thay đổi nó. Những giả định và tìm kiếm tất cả các nơi tốt nhất là tránh. – FakeRainBrigand

3

Bạn có thể refs chuỗi, vì vậy nếu bạn kéo một phần tử bằng cách ref, bạn có thể lấy refs bên trong phần tử rằng:

Xác định lớp Outer của bạn như Outer = React.createClass render: -> div { id: 'myApp' }, Inner {ref: 'inner'}

sẽ cho phép sau đó bạn lấy thông tin đầu vào với @refs.inner.refs.myInput.getDOMNode() để gọi focus vào.

+1

Cảm ơn câu trả lời của bạn, nhưng tôi thích giải pháp của @ssorallen, trông sạch hơn với tôi. – octref

Các vấn đề liên quan