2016-07-29 15 views
8

Tôi cố gắng sử dụng ref ít nhất có thể, nhưng có vẻ như không có cách nào xung quanh nó để gọi các phương thức dom (focus(), reset(), blur() v.v.) với. Trừ, tôi muốn sử dụng các chức năng thành phần không quốc tịch cho những thứ cơ bản như đầu vào biểu mẫu, khi nó đứng, các thành phần không trạng thái này không cho phép ref trỏ đến chúng (chúng sẽ trả về null). Tôi hiểu rằng tôi có thể thêm một wrapper thành phần lớp React thường xuyên xung quanh thành phần không trạng thái để cho phép ReactDOM.findDOMNode (ref) hoạt động chính xác, nhưng điểm nào có chức năng không trạng thái nếu nó luôn luôn được bao bọc? Tui bỏ lỡ điều gì vậy?Có thể gọi các phương thức phần tử dom như focus() mà không sử dụng ref? (Sử dụng các hàm thành phần không có trạng thái)

Trả lời

5

Đây là giải pháp mà tôi đã đưa ra mà không yêu cầu gói thành phần không trạng thái trong một lớp học. Thay vào đó, nó liên quan đến việc cha mẹ chuyển một hàm tới thành phần không trạng thái như một nhánh được sử dụng như hàm gọi lại cho ref trên phần tử DOM.

Trước tiên hãy đặt một phương thức trên phụ huynh trạng thái sẽ được sử dụng làm gọi lại cho ref và phương thức khác để thực hiện hành động trên phần tử DOM (trong trường hợp này tập trung sau khi nhấn phím). Sau đó gửi phương thức cho đứa trẻ không quốc tịch như một biện pháp chống đỡ.

// note: Facebook now recommends using native js classes instead of React.createClass(). 
// note 2: You may need Babel to transpile some of ES6 syntax in use here. 

const StatefulParent = React.createClass({ 
    getInitialState() { 
    return { 
     // doesn't matter for this example 
    } 
    }, 
    componentDidMount() { 
    document.addEventListener('keyup', this.keyUp, false) 
    }, 
    keyUp() { 
    // calls the DOM focus method on the input when the 'tab' key is pressed 
    if (e.keyCode === 9) this._input.focus() 
    }, 
    inputSetter(ref) { 
    this._input = ref 
    }, 
    render() { 
    <StatelessTextInput {...this.state} refCallback={this.inputSetter} /> 
    } 
}) 

Thành phần không trạng thái giả định phương thức sẽ được chuyển đến phương thức đó từ cha mẹ được gọi là refCallback. Prop này có thể được truyền qua bất kỳ số lượng các thế hệ thành phần nào để đạt được phần tử DOM.

const StatelessTextInput = ({refCallback, ...props}) => (
    <input {...props} ref={refCallback} /> 
) 
+0

Cảm ơn bạn! Điều này rất hữu ích! –

1

Chỉ cần bọc thành phần không trạng thái của bạn với thành phần lớp (es6) đính kèm ref. Nó được viết trong official docs

+4

Chắc chắn nhưng điểm tạo ra chức năng không quốc tịch là gì nếu bạn phải quấn nó trong một lớp học? Cũng có thể chỉ cần sử dụng một lớp học để bắt đầu trong trường hợp đó. –

+0

Các chức năng không quốc tịch giống như các chức năng thuần túy và sử dụng cho mục đích trình bày. Chỉ cần lấy các đạo cụ và render xem mà không có bất kỳ tác dụng phụ. Vì vậy, nếu thành phần của bạn cần một số hành vi không tầm thường, đó là thời gian để trích xuất thành phần lớp. – andreo

0

Giải pháp sạch nhất tôi tìm thấy là đặt biến cục bộ và sau đó gán cho nó. Sau đó, điều này có thể được truy cập và tập trung khi cần thiết:

const Item =() => { 
    let input; 

    const click =() => { 
     if (input){ 
      input.focus(); 
     } 
    }; 
    return (
     <div> 
      <a href="#" onClick={click}>clickMe</a> 
      <input ref={e => (input = e)}/> 
     </div> 
    ); 

}; 
+0

Vâng, điều đó rất dễ dàng nếu bạn đang phát hành lại một phần tử html trong phần cha mẹ trực tiếp của nó. Nhưng nếu có một mức độ tách biệt khác (một ông bà cần ref của một đứa cháu) và thành phần ở giữa (cha mẹ) là một chức năng không quốc tịch ... đó là kịch bản tôi đưa ra. –

0

có, chỉ nhớ nó trong khi hiển thị và mang nó ra, và tập trung vào nó sau khi hiển thị:

function Main(props) { 
    <input ref={e => { props.elems.input = e; }} 
} 
const elems = {}; 
ReactDOM.render(Main({ elems }), containerElement); 

elems.input.focus(); 
0

Chỉ có vấn đề này quá với một thành phần không trạng thái. Ít nhất là React v16, bạn có thể tham khảo phần tử như thế này:

<Button 
    onClick={(el) => { 
    el.target.blur(); 
    }}> 
    Button Text 
</Button> 
Các vấn đề liên quan