React 15.2.0を使い始めたら・・・!!!
React15.2.0がリリースされました。エラー周りが強くなっててこれはいいぞ!と使っていたところ、redux-formを実装したら、warningが吐き出されるようになっていた。
warningの内容は
bundle.js:1309 Warning: Unknown props
initialValue
,autofill
,onUpdate
,valid
,invalid
,dirty
,pristine
,active
,touched
,visited
,autofilled
on<input>
tag. Remove these props from the element. For details, see
よくわかんないpropsを渡さないでくださいよ!
ということらしい。どうやらReact 15.2.0では予期しないprops(属性として設定できない値)を渡すとWarningが出る模様。
redux-formを使う際には
<input type="text" {...this.props.fields.txt} />
このようにスプレッド演算子を使って書くことが多いというか公式のサンプルもそうなっている。すると、this.props.fields.txtには、
{
active:false,
autofill:(value),
autofilled:false,
checked:undefined,
dirty:false,
initialValue:"",
invalid:false,
name:"txt",
onBlur:(event),
onChange:(event),
onDragStart:(event),
onDrop:(event),
onFocus:(),
onUpdate:(event),
pristine:true,
touched:false,
valid:true,
value:"",
visited:false
}
とたくさんのプロパティが詰め込まれている。
そのため本来はinputで扱えない属性も設定してしまっていることが原因らしい。。。
対策
並行してMaterial-uiも使っていたがそちらでも一部コンポーネントについてはWarningが出ていたため、めんどくさくなり15.1.0に戻したが後日、改めてredux-formでの対策を調べてみた。
V5で必要ないプロパティを取り除く
import React, {Component} from 'react';
import {render} from 'react-dom';
import { createStore, combineReducers,applyMiddleware } from 'redux'
import { Provider } from 'react-redux';
import { reduxForm, reducer, Field } from 'redux-form';
import createLogger from 'redux-logger';
const logger = createLogger();
let obj = combineReducers({form:reducer});
const store = createStore(obj,applyMiddleware(logger));
class App extends Component{
render(){
return (
<Provider store={store}>
<Main />
</Provider>
);
}
}
class Mainpre extends Component{
constructor(props){
super(props);
this.InputProps = [
// HTML attributes
"placeholder",
"type",
"value",
// Event listeners
"onBlur",
"onChange",
"onFocus",
];
}
render(){
return (
<div>
<input
type="text"
{..._.pick(this.props.fields.txt, this.InputProps)}
/>
</div>
);
}
}
const Main = reduxForm({
form:'test',
fields:['txt']
})(Mainpre);
render(<App />, document.getElementById('content'));
これで警告がでるようなプロパティを除いて渡すこと警告がなくなります。underscore.jsを使ってますが、自作でもいいかもしれません。
V6を使う
redux-formV6でも回避できます。
import React, {Component} from 'react';
import {render} from 'react-dom';
import { createStore, combineReducers,applyMiddleware } from 'redux'
import { Provider } from 'react-redux';
import { reduxForm, reducer, Field } from 'redux-form';
import createLogger from 'redux-logger';
const logger = createLogger();
let obj = combineReducers({form:reducer});
const store = createStore(obj,applyMiddleware(logger));
class App extends Component{
render(){
return (
<Provider store={store}>
<Main />
</Provider>
);
}
}
class Mainpre extends Component{
constructor(props){
super(props);
}
render(){
return (
<div>
<Field name="txt" component="input" type="text"/>
</div>
);
}
}
const Main = reduxForm({
form:'test',
})(Mainpre);
render(<App />, document.getElementById('content'));
具体的にはreduxForm()()からfieldsプロパティがなくなり、Fieldコンポーネントにname="txt"として指定しています。
また、component="input"として、inputを指定していますが、自分で作ったコンポーネントを使いたい時は
<Field name="txt" component={customComponent} type="text"/>
このようにして、CustomComponent側では、
const customComponent = props =>(
<div>
<input {...props.input}/>
</div>
);
として受けます。
ご不明点、間違い、こうした方がいいなどございましたらご指摘頂けますと幸いです。