公式サイトではjQueryプラグイン(Chosen)のラッパーのサンプルコードが掲載されていますが
実際に要素を追加したときの動きの違いを確認しました。
componentDidUpdate
にあるChosenライブライのtriggerを呼び出さないと、
Reactがstateの変化を検知してrenderを実行してもChosenが生成するドロップダウンのリストには反映されません。
App.js
import React, { Component } from "react";
import "./App.css";
import $ from "jquery";
import "chosen-js/chosen.css";
import "chosen-js/chosen.jquery.js";
class Chosen extends React.Component {
componentDidMount() {
this.$el = $(this.el);
this.$el.chosen();
this.handleChange = this.handleChange.bind(this);
this.$el.on("change", this.handleChange);
}
componentDidUpdate(prevProps) {
if (prevProps.children !== this.props.children) {
this.$el.trigger("chosen:updated"); //ここをコメントアウトすると・・・
}
}
componentWillUnmount() {
this.$el.off("change", this.handleChange);
this.$el.chosen("destroy");
}
handleChange(e) {
this.props.onChange(e.target.value);
}
render() {
return (
<div>
<select className="Chosen-select" ref={el => (this.el = el)}>
{this.props.children}
</select>
</div>
);
}
}
class App extends Component {
constructor(prpps) {
super(prpps);
this.state = {
items: ["one", "two", "three"]
};
}
handleAddList = () => {
this.setState({ items: this.state.items.concat(["four"]) });
};
render() {
return (
<div className="App">
<button onClick={this.handleAddList}>追加</button>
{/* Reactの守備範囲外 */}
<Chosen onChange={value => console.log(value)}>
{this.state.items.map(item => (
<option key={}>{item}</option>
))}
</Chosen>
{/* Reactの守備範囲 */}
<select>
{this.state.items.map(item => (
<option key={item}>{item}</option>
))}
</select>
</div>
);
}
}
export default App;
componentDidUpdate
をコメントアウトした場合、追加ボタンによって新たな要素が追加され
DOMには4つめの要素が生成されますが、Chosenが生成しているSelectには表示されません。
もちろん、普通のを利用しているリストには追加した要素が表示されます。
基本的にはReactのComponentとして提供されているライブラリを利用する方がよいですが、
必要に迫られた場合には、やれないことはないということですね。