LoginSignup
15
9

More than 5 years have passed since last update.

React.jsで"Unknown prop"に立ち向かう

Last updated at Posted at 2016-08-30

はじめに

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

闇の方法だけど成功😇

おまけ

ボタンを装飾する

スクリーンショット 2016-09-01 14.11.19.png

コードは以下

"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>
        );
    }
}
15
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
9