1. ホーム
  2. reactjs

[解決済み] Reactでステートレスコンポーネントのrefにアタッチするにはどうすればよいですか?

2023-05-31 07:05:04

質問

ステートレス・コンポーネントを作成しようとしています。 input 要素が親コンポーネントによって検証されます。

以下の例では、入力の ref が親のプライベートな _emailAddress プロパティに割り当てられることはありません。

いつ handleSubmit が呼び出されます。 this._emailAddressundefined . 何か見落としているのか、それとももっと良い方法があるのでしょうか?

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

どのように解決するのですか?

編集:あなたは今、React Hooksを使用することができます。Ante Gulinの回答を参照してください。

Reactライクなメソッド(例えば componentDidMount , componentWillReceiveProps など) を含むステートレス・コンポーネントに refs . GH でのこのディスカッションをチェックアウトする をご覧ください。

ステートレスの考え方は、そのためのインスタンス(状態)が作成されないということです。そのため ref というように、refをアタッチするステートがないためです。

最善の策は、コンポーネントが変更されたときのコールバックを渡し、そのテキストを親のステートに割り当てることでしょう。

または、ステートレス・コンポーネントを完全に見送って、通常のクラス・コンポーネントを使用することもできます。

ドキュメントから...

<ブロッククオート

関数型コンポーネントはインスタンスを持たないので、ref属性を使用することはできません。しかし、機能コンポーネントの render 関数内部で ref 属性を使用することはできます。

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