Tìm kiếm trang web

reactjs - Làm thế nào tôi có thể gắn ref vào một component không trạng thái trong React?


Tôi đang muốn tạo một component không trạng thái mà input của nó có thể được component cha xác thực.

Trong ví dụ của tôi dưới đây, tôi đang gặp phải vấn đề khi giá trị nhập ref không bao giờ được gán cho thuộc tính riêng _emailAddress của đối tượng cha.

Khi handleSubmit được gọi, this._emailAddress là undefined. Có phải tôi đang bỏ lỡ điều gì đó, hay có cách nào tốt hơn để làm việc này không?

interface FormTestState {
    errors: string;
}

class FormTest extends React.Component<void, FormTestState> {
    componentWillMount() {
        this.setState({ errors: '' });
    }

    render(): JSX.Element {
        return (
            <main role='main' className='about_us'>             
                <form onSubmit={this._handleSubmit.bind(this)}>
                    <TextInput 
                        label='email'
                        inputName='txtInput'
                        ariaLabel='email'
                        validation={this.state.errors}
                        ref={r => this._emailAddress = r}
                    />

                    <button type='submit'>submit</button>
                </form>
            </main>
        );
    }

    private _emailAddress: HTMLInputElement;

    private _handleSubmit(event: Event): void {
        event.preventDefault();
        // this._emailAddress is undefined
        if (!Validators.isEmail(this._emailAddress.value)) {
            this.setState({ errors: 'Please enter an email address.' });
        } else {
            this.setState({ errors: 'All Good.' });
        }
    }
}

const TextInput = ({ label, inputName, ariaLabel, validation, ref }: { label: string; inputName: string; ariaLabel: string; validation?: string; ref: (ref: HTMLInputElement) => void }) => (
    <div>
        <label htmlFor='txt_register_first_name'>
            { label }
        </label>

        <input type='text' id={inputName} name={inputName} className='input ' aria-label={ariaLabel} ref={ref} />

        <div className='input_validation'>
            <span>{validation}</span>
        </div>
    </div>
);

Câu trả lời #1

Bạn có thể sử dụng hook useRef có sẵn từ v16.7.0-alpha.

CHỈNH SỬA: Bạn được khuyến khích sử dụng Móc trong quá trình sản xuất bắt đầu từ phiên bản 16.8.0!

Hooks cho phép bạn duy trì trạng thái và xử lý các hiệu ứng phụ trong các thành phần hàm.

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

Đọc thêm trong tài liệu API Hooks

Câu trả lời #2

CHỈNH SỬA: Bây giờ bạn có thể thực hiện việc này với React Hooks. Xem câu trả lời của Ante Gulin.

Bạn không thể truy cập các phương thức giống React (như componentDidMount, componentWillReceiveProps, v.v.) trên các component không có trạng thái, bao gồm cả refs. Xem cuộc thảo luận này trên GitHub để biết toàn bộ cuộc trò chuyện.

Ý tưởng về stateless là không có một thể hiện (instance) nào được tạo ra cho nó (state). Vì vậy, bạn không thể gắn một ref, vì không có state nào để gắn ref vào.

Điều tốt nhất bạn nên làm là truyền một callback khi component thay đổi và sau đó gán văn bản đó cho state của component cha.

Hoặc, bạn có thể bỏ qua hoàn toàn thành phần không trạng thái và sử dụng một thành phần lớp bình thường.

Từ các tài liệu...

Bạn không thể sử dụng thuộc tính ref trên các thành phần chức năng vì chúng không có thực thể. Tuy nhiên, bạn có thể sử dụng thuộc tính ref bên trong hàm render của một thành phần chức năng.

function CustomTextInput(props) {
  // textInput must be declared here so the ref callback can refer to it
  let textInput = null;

  function handleClick() {
    textInput.focus();
  }

  return (
    <div>
      <input
        type="text"
        ref={(input) => { textInput = input; }} />
      <input
        type="button"
        value="Focus the text input"
        onClick={handleClick}
      />
    </div>
  );  
}

Bài viết liên quan