はじめに
React.jsを使っていて、こんなことを言われたことはないだろうか
Warning: Unknown prop `webkitdirectory` on <input> tag. Remove this prop from the element. For details, see https://fb.me/react-unknown-prop
Chromeでしか使えないプロパティにつく接頭辞"webkit"ではあるが、使えてほしい。
tl;dr
render()では該当するattributeを書かず、componentDidMountで追加すれば良い
ISSUEを確認してみる
ISSUE#3468: JSX render won't allow webkitdirectory and directory to be used
まさにこれ
とりあえずwhitelistに書かれたプロパティしか認めてないから、それ以外はunkonws propらしい
多くのcomponentが子要素にプロパティを渡しすぎているから、ISSUE#140にあるけどしばらく修正不可らしい
でも、ISSUE#3468の中に、解決された、と参照されているPRがある。
PR#3644: Add webkitdirectory and nwdirectory attributes for input file
Merged!?とおもいきや一番下でReverted...
理由は
- たとえ本来のプロパティ名がキャメルケースでなくても、reactでは全てキャメルケースにしている
- まだ標準ではないし、むやみにサポートするべきでもない
とのこと
う〜んわかるけど使いたい!!!
解決策
render()では該当するattributeを書かず、componentDidMountで追加すれば良い
"use strict";
import React from 'react';
import ReactDOM from 'react-dom';
export default class FileInput extends React.Component {
componentDidMount() {
let node = this._input;
node.webkitdirectory = true;
node.directory = true;
}
render() {
return (
<input type="file" ref={(c) => {this._input = c;}} {...this.props} />
);
}
}
闇の方法だけど成功😇
おまけ
ボタンを装飾する
コードは以下
"use strict";
import React from 'react';
import ReactDOM from 'react-dom';
export default class FileInput extends React.Component {
constructor(props) {
super(props);
this.state = {
hover: false
};
}
componentDidMount() {
let node = ReactDOM.findDOMNode(this.refs.filesInput)
node.webkitdirectory = true;
node.directory = true;
}
onMouseEnter() {
this.setState({hover: true});
}
onMouseLeave() {
this.setState({hover: false});
}
render() {
let labelStyle = {
color: "brown",
backgroundColor: "transparent",
border: "solid 2px brown",
boxSizing: "border-box",
padding: 20,
borderRadius: 12
}
let hoverLabelStyle = {
color: "white",
backgroundColor: "brown",
border: "solid 2px brown",
boxSizing: "border-box",
padding: 20,
borderRadius: 12
}
return (
<label htmlFor="file-input" style={this.state.hover ? hoverLabelStyle : labelStyle} onMouseEnter={this.onMouseEnter.bind(this)} onMouseLeave={this.onMouseLeave.bind(this)}>
+フォルダを選択
<input type="file" id="file-input" ref="filesInput" style={{display: "none"}} {...this.props} />
</label>
);
}
}