反応コンポーネントの内部にサードパーティのライブラリを使用するのが面倒なバグがあります。私はこのポストのために考案されたデモを再現することができました。React.jsサードパーティのライブラリ実装を扱う
チャートライブラリであるc3jsを使って、componentDidMount()
にレンダリングし、への正しい呼び出しでcomponentWillUnmount()
でそれを取り除くことから説明しましょう。
コンポーネント自体をフィルタリングするときにバグが発生します。基本的にはコンポーネントが正しくフィルタリングされますが、コンポーネント内にある実際のチャートは最初のチャートと同じままです。基本的に間違ったコンポーネントの内部にある間違ったチャートです!
Remove all charts except chart 3
ボタンをクリックすると、図表にchartid
というラベルが付けられ、フィルタリングによって他の図が正しく削除されます。
フィルタリングが正しく機能し、ビューが更新されるため、私のコードではありません。グラフにラベルを付けて、ビューに表示できるので、確認できます。コンソールエラーはなく、自分のコードが動作していることを確認しました。
私の質問は - c3jsを使ってこの制限を回避することができますか、これは実際に私のコードとチャートをレンダリングする方法の問題です。
関連デモ:https://jsfiddle.net/69z2wepo/38614/
関連コード:
var data = [
{
chartid: 1,
columns: [
['x', 0, 1, 2, 3, 4, 5, 6],
['data1', 130, 300, 330, 400, 300, 400, 500],
['data2', 390, 230, 200, 150, 100, 130, 210],
['data3', 290, 430, 300, 160, 210, 170, 190],
['data4', 190, 330, 200, 260, 190, 250, 320]
]
},
{
chartid: 2,
columns: [
['x', 0, 1, 2, 3, 4, 5, 6],
['data1', 130, 300, 330, 400, 300, 400, 500],
['data2', 390, 230, 200, 150, 100, 130, 210],
['data3', 290, 430, 300, 160, 210, 170, 190]
]
},
{
chartid: 3,
columns: [
['x', 0, 1, 2, 3, 4, 5, 6],
['data1', 130, 300, 330, 400, 300, 400, 500],
['data2', 390, 230, 200, 150, 100, 130, 210]
]
}
];
var Button = React.createClass({
handleDelete: function (id) {
this.props.handleDelete(id);
},
render: function() {
return (
<button onClick={this.handleDelete.bind(null, 3)}>
Remove all charts except chart 3
</button>
)
}
});
var Chart = React.createClass({
componentDidMount() {
this.chart = c3.generate({
bindto: '.chart-' + this.props.data.chartid,
data: {
columns: this.props.data.columns
}
});
},
componentWillUnmount() {
this.chart.destroy();
},
render: function() {
return (
<div>
<h4>{"chart-" + this.props.data.chartid}</h4>
<div className={"chart-" + this.props.data.chartid}>
</div>
</div>
)
}
});
var Child = React.createClass({
renderCharts: function(data) {
return data.map(function(metrics, i) {
return (
<Chart key={i} data={metrics} />
)
});
},
handleDelete: function(id) {
this.props.handleDelete(id);
},
render: function() {
return (
<div>
<Button handleDelete={this.handleDelete} />
{this.renderCharts(this.props.data)}
</div>
)
}
})
var App = React.createClass({
getInitialState: function() {
return {
initialData: this.props.data
}
},
handleDelete: function(id) {
var _filterFunc = function(data) {
if (data.chartid == id) return true;
return false;
};
var _filterCharts = Array.prototype.filter.call(this.state.initialData, _filterFunc);
this.setState({
initialData: _filterCharts
})
},
render: function() {
return (
<div>
<Child handleDelete={this.handleDelete} data={this.state.initialData} />
</div>
);
}
});
ReactDOM.render(
<App data={data} />,
document.getElementById('container')
);
はい、あなたは正しいです!私が割り当てていたキーは実際に 'map'ループに基づいていて実際にチャートには関係していなかったので、チャート3はフィルタリングされているときに' key = {1} 'を受け取りました。私はそれを述べて正しいですか? – AntonB
これはまさに正しいことです。振る舞いはちょっと直感的ではありませんが、Reactには高いパフォーマンスが得られるような最適化があることを覚えておいてください。 – TAGraves