親コンポーネントによって検証できるinput
要素のステートレスコンポーネントを作成しようとしています。
以下の例では、入力ref
が親のプライベート_emailAddress
プロパティに割り当てられないという問題に直面しています。
handleSubmit
が呼び出されると、this._emailAddress
はundefined
になります。私が不足しているものがありますか、これを行うためのより良い方法はありますか?
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フックでできるようになりました。アンテ・グリンの回答をご覧ください。
componentDidMount
などのステートレスコンポーネント上のReactのようなメソッド(componentWillReceiveProps
、refs
など)にアクセスすることはできません。 GHに関するこの議論をチェックアウト 完全なコンボについて。
ステートレスの考え方は、そのために作成されたインスタンス(状態)がないということです。そのため、refをアタッチする状態がないため、ref
をアタッチすることはできません。
最善の策は、コンポーネントが変更されたときにコールバックを渡し、そのテキストを親の状態に割り当てることです。
または、ステートレスコンポーネントを完全に放棄し、通常のクラスコンポーネントを使用できます。
機能コンポーネントにはインスタンスがないため、機能コンポーネントでref属性を使用することはできません。ただし、機能コンポーネントのレンダリング関数内で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>
);
}
v16.7.0-alpha
以降使用可能なuseRef
フックを使用できます。
EDIT:16.8.0
リリース時点で、本番環境でフックを使用することをお勧めします!
フックを使用すると、機能コンポーネントの状態を維持し、副作用を処理できます。
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>
</>
);
}
詳しくは フックAPIドキュメント をご覧ください
TextInputの値は、コンポーネントの状態にすぎません。そのため、参照を使用して現在の値を取得する代わりに(私が知る限り、一般的に悪い考えです)、現在の状態を取得できます。
縮小版(入力なし):
class Form extends React.Component {
constructor() {
this.state = { _emailAddress: '' };
this.updateEmailAddress = this.updateEmailAddress.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
updateEmailAddress(e) {
this.setState({ _emailAddress: e.target.value });
}
handleSubmit() {
console.log(this.state._emailAddress);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input
value={this.state._emailAddress}
onChange={this.updateEmailAddress}
/>
</form>
);
}
}