Material-UI を使っていて以下のように書いたところ、警告が出た。
<TextField
ref={(element) => this.textField = element}
label="ID"
className={classes.textField}
value={name}
margin="normal"/>
Warning: Stateless function components cannot be given refs. Attempts to access this ref will fail.
そもそも ref ってよくわかっていない
Refs provide a way to access DOM nodes or React elements created in the render method.
render() で作った DOM node や React elements にアクセスするための方法を提供してくれるとのこと。
String Refs
これは deprecated (廃止予定) なので使わないほうが良い。
https://reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs
class StringRefs extends React.Component {
handleClick = () => {
console.log(this.refs.inputEl.value) // aaa
}
render() {
return (
<div>
<input type="text" ref="inputEl" defaultValue="aaa" />
<button type="button" onClick={this.handleClick}/>
</div>
)
}
}
Callback Refs
これが現状主流なのかな?
https://reactjs.org/docs/refs-and-the-dom.html#callback-refs
class CallbackRefs extends React.Component {
handleClick = () => {
console.log(this.inputEl.value) // aaa
}
render() {
return (
<div>
<input type="text"
ref={(element) => {
this.inputEl = element
}}
defaultValue="aaa" />
<button type="button" onClick={this.handleClick}/>
</div>
)
}
}
Creating Refs
React v16.3 から使えるようになった方法。こっちの方がわかりやすいかも。
class CreatingRefs extends React.Component {
inputEl = React.createRef()
handleClick = () => {
console.log(this.inputEl.current.value) // aaa
}
render() {
return (
<input type="text" ref={this.inputEl} defaultValue="aaa"/>
<button type="button" onClick={this.handleClick}/>
)
}
}
本題に戻る
Warning: Stateless function components cannot be given refs. Attempts to access this ref will fail.
Stateless function components っていうのは引数で渡ってきた props 以外は使えないコンポーネント(実質ただの関数)っぽい。
function CustomTextInput(props) {
return (
<div>
<input ref={props.inputRef} />
</div>
);
}
class Parent extends React.Component {
render() {
return (
<CustomTextInput
inputRef={el => this.inputElement = el}
/>
);
}
}
こんなノリにすると子コンポーネントの input の ref を親コンポーネントで扱えるらしい
https://material-ui.com/api/text-field/
を見てみたらまったく同じプロパティあるやん!というわけで、
<TextField
inputRef={(element) => this.textField = element}
label="ID"
className={classes.textField}
value={name}
margin="normal"/>
で警告が消えた。