Rork アプリで「月別の収入と支出を横並びの棒グラフで比較したい」と思ったとき、真っ先に試すのが react-native-chart-kit の BarChart コンポーネントです。ところが、ドキュメントをひと通り読んでから実装してみると、こんな壁にぶつかります。
// こう書きたいのに動かない
const data = {
labels: ["1月", "2月", "3月"],
datasets: [
{ data: [30000, 45000, 38000], color: () => "#4CAF50" }, // 収入
{ data: [22000, 31000, 29000], color: () => "#F44336" }, // 支出
],
};このコードを BarChart に渡しても、2本目のデータセットは表示されません。react-native-chart-kit の BarChart は設計上、単一の datasets[0] しか参照しない実装になっているためです。
同じ問題で検索している開発者が世界中にいるのを見ると、これはライブラリの大きな欠点の一つだと感じます。Rork アプリで複数データセットの棒グラフを実現するための実用的な3つのアプローチを順番にご紹介します。
なぜ chart-kit の BarChart は複数データセットに対応していないのか
react-native-chart-kit のソースコードを確認すると、BarChart.tsx は内部で data.datasets[0].data だけを参照する設計です。LineChart は複数 datasets を重ね描きできる実装になっているのと対照的で、同じライブラリなのにコンポーネントごとに対応状況が異なります。
ライブラリの GitHub Issues には複数データセット対応の要望が複数上がっていますが、2026年時点でもコアの BarChart は改善されていません。
この制限を前にしたとき、取れるアプローチは大きく3つあります。
アプローチ1:色分けで「擬似グループ」を作る(最もシンプル)
厳密な横並び表示ではありませんが、月別データをひとつの配列に連結し、ラベルと色で視覚的に区別する方法です。実装が最もシンプルで、簡単な比較グラフには十分実用的です。
import { BarChart } from "react-native-chart-kit";
import { Dimensions } from "react-native";
const screenWidth = Dimensions.get("window").width;
// 収入と支出のデータを交互に並べる
const data = {
labels: ["1月収", "1月支", "2月収", "2月支", "3月収", "3月支"],
datasets: [
{
data: [30000, 22000, 45000, 31000, 38000, 29000],
// 偶数インデックス(収入)は緑、奇数(支出)は赤
colors: [
() => "#4CAF50",
() => "#F44336",
() => "#4CAF50",
() => "#F44336",
() => "#4CAF50",
() => "#F44336",
],
},
],
};
export default function IncomeExpenseChart() {
return (
<BarChart
data={data}
width={screenWidth - 32}
height={220}
yAxisLabel="¥"
yAxisSuffix=""
withCustomBarColorFromData={true} // ← 色配列を有効にするフラグ
flatColor={true}
chartConfig={{
backgroundColor: "#ffffff",
backgroundGradientFrom: "#ffffff",
backgroundGradientTo: "#ffffff",
decimalPlaces: 0,
color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
}}
style={{ borderRadius: 8 }}
/>
);
}ポイント: withCustomBarColorFromData={true} と flatColor={true} の組み合わせが必要です。この2つが揃って初めて colors 配列が反映されます。どちらか片方だけでは期待通りに動かないので注意してください。
限界: ラベルが横長になりやすく、月数が増えると読みにくくなります。3ヶ月程度のシンプルな比較には向いていますが、12ヶ月を並べるには向きません。
アプローチ2:2つの BarChart を重ねて表示する
position: "absolute" で2枚の BarChart を重ねることで、視覚的に横並びに近い表現が可能です。少しハックな実装ですが、chart-kit の範囲内で最も見た目の自由度が高い方法です。
import { View } from "react-native";
import { BarChart } from "react-native-chart-kit";
import { Dimensions } from "react-native";
const screenWidth = Dimensions.get("window").width;
const chartWidth = screenWidth - 32;
const baseConfig = {
backgroundColor: "transparent",
backgroundGradientFrom: "transparent",
backgroundGradientTo: "transparent",
decimalPlaces: 0,
color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
};
// 収入データ(左側に寄せたい)
const incomeData = {
labels: ["1月", "2月", "3月"],
datasets: [{ data: [30000, 45000, 38000] }],
};
// 支出データ(右側に寄せたい)
const expenseData = {
labels: [" ", " ", " "], // 空ラベルでY軸を非表示にしない
datasets: [{ data: [22000, 31000, 29000] }],
};
export default function GroupedBarChart() {
return (
<View style={{ height: 220, position: "relative" }}>
{/* 背景:収入グラフ(軸・ラベルあり) */}
<BarChart
data={incomeData}
width={chartWidth}
height={220}
yAxisLabel="¥"
yAxisSuffix=""
chartConfig={{
...baseConfig,
color: () => "#4CAF50", // 収入は緑
backgroundColor: "#ffffff",
backgroundGradientFrom: "#ffffff",
backgroundGradientTo: "#ffffff",
}}
style={{ position: "absolute", left: 0, top: 0 }}
/>
{/* 前景:支出グラフ(背景を透明に) */}
<BarChart
data={expenseData}
width={chartWidth}
height={220}
yAxisLabel=""
yAxisSuffix=""
chartConfig={{
...baseConfig,
color: () => "#F44336", // 支出は赤
backgroundColor: "transparent",
backgroundGradientFrom: "transparent",
backgroundGradientTo: "transparent",
}}
style={{ position: "absolute", left: 0, top: 0 }}
/>
</View>
);
}正直な感想: この方法はY軸の位置合わせやバーの幅調整が難しく、実用的に仕上げるまでに時間がかかります。シンプルな比較で良いなら、後述の Victory Native への移行を検討する方が長期的には早いかもしれません。
アプローチ3:Victory Native でグループ棒グラフを実装する(推奨)
react-native-chart-kit の BarChart の制限に向き合うほど、Victory Native に乗り換えた方が早い という結論に行き着くことが多いです。Victory Native は複数データセットのグループ棒グラフをネイティブにサポートしており、Rork との相性も良好です。
import { VictoryBar, VictoryChart, VictoryGroup, VictoryAxis, VictoryTheme } from "victory-native";
const incomeData = [
{ x: "1月", y: 30000 },
{ x: "2月", y: 45000 },
{ x: "3月", y: 38000 },
];
const expenseData = [
{ x: "1月", y: 22000 },
{ x: "2月", y: 31000 },
{ x: "3月", y: 29000 },
];
export default function GroupedBarChartVictory() {
return (
<VictoryChart
theme={VictoryTheme.material}
domainPadding={{ x: 30 }}
height={300}
>
<VictoryAxis
tickValues={["1月", "2月", "3月"]}
style={{ tickLabels: { fontSize: 12, fill: "#333" } }}
/>
<VictoryAxis
dependentAxis
tickFormat={(t) => `¥${(t / 1000).toFixed(0)}k`}
style={{ tickLabels: { fontSize: 11, fill: "#333" } }}
/>
{/* VictoryGroup でバーをグループ化 */}
<VictoryGroup
offset={15} // グループ内のバー間隔
colorScale={["#4CAF50", "#F44336"]}
>
<VictoryBar data={incomeData} />
<VictoryBar data={expenseData} />
</VictoryGroup>
</VictoryChart>
);
}このコードは、収入と支出を月ごとに横並び表示する グループ棒グラフ を実現します。VictoryGroup の offset プロパティでバー間の間隔を調整できるため、見た目の調整も直感的です。
Victory Native のインストールは以下のコマンドで行います:
# Expo プロジェクトの場合
npx expo install victory-native react-native-svg
# または npm
npm install victory-native react-native-svgVictory Native を使ったダッシュボード全体の実装については、Rork アプリにインタラクティブなチャートを実装する — Victory Native 実践ガイドでより詳しく解説しています。
どのアプローチを選ぶべきか
既にプロジェクトで react-native-chart-kit を使っていて、1〜2箇所だけグループ棒グラフが必要なら、アプローチ1(色分けシミュレーション) で素早く解決できます。
一方、グラフの種類が増える可能性があったり、今後も複雑なデータ可視化を追加する予定があるなら、この機会に Victory Native への移行 を検討することをおすすめします。2つのライブラリを混在させるよりも、1つのライブラリで統一した方が長期的なメンテナンスが楽です。
アプリの種類によって最適な選択は変わりますが、複数データセットを比較表示するグラフが必要になるアプリ(家計簿、フィットネス、ビジネスダッシュボードなど)では、最初から Victory Native を選んでおいた方が後悔が少ないと思います。
React Native のデータ可視化について体系的に
それぞれのアプローチのトレードオフを把握した上で、プロジェクトの規模と今後の方向性に合った選択をしてみてください。まずは アプローチ1 でサクッと動かして確認し、物足りなければ Victory Native に移行するという流れが、開発のリズムを崩さずに進められると思います。
chart-kit BarChart でよくある追加の落とし穴
複数データセットの問題以外にも、react-native-chart-kit の BarChart で詰まりやすいポイントをいくつか整理しておきます。
fromZero を付け忘れると比較グラフが歪む
fromZero={true} がないと、Y軸の最小値がデータの最小値付近から始まります。2つの値が近い場合でも大きな差があるように見えてしまうため、棒グラフには必ず fromZero={true} を指定することをおすすめします。
<BarChart
data={data}
fromZero={true} // ← 必須
// ...他のprops
/>showValuesOnTopOfBars と大きな数値の組み合わせ
showValuesOnTopOfBars={true} を有効にすると、各バーの上に値ラベルが表示されます。ただし、30000 のような5桁以上の数値だとラベルがチャート外にはみ出すことがあります。データを千単位に正規化して yAxisSuffix="k" を付けるか、値の表示は諦めてY軸のメモリだけで読み取れる設計にするのが現実的です。
legend プロパティは chart-kit にない
react-native-chart-kit の BarChart には凡例(legend)を自動生成するプロパティがありません。複数データを色分けした場合、ユーザーが色の意味を理解できるよう、チャートの下に手動で凡例コンポーネントを追加する必要があります。
// シンプルな凡例コンポーネント
import { View, Text, StyleSheet } from "react-native";
function Legend() {
return (
<View style={styles.row}>
<View style={styles.item}>
<View style={[styles.dot, { backgroundColor: "#4CAF50" }]} />
<Text style={styles.label}>収入</Text>
</View>
<View style={styles.item}>
<View style={[styles.dot, { backgroundColor: "#F44336" }]} />
<Text style={styles.label}>支出</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
row: { flexDirection: "row", justifyContent: "center", gap: 20, marginTop: 8 },
item: { flexDirection: "row", alignItems: "center", gap: 6 },
dot: { width: 10, height: 10, borderRadius: 5 },
label: { fontSize: 13, color: "#555" },
});<BarChart /> の直下に <Legend /> を配置するだけで、視認性が大きく改善します。
chart-kit を使い続けるか乗り換えるかの判断基準
react-native-chart-kit は、シンプルな単一データのグラフが必要な場合には十分な選択肢です。セットアップが簡単で、デフォルトのスタイルも悪くありません。
ただ、複数データセットの比較グラフが必要になった時点で、データ可視化の要件がアプリの中心的な機能になりつつあるサインかもしれません。そのフェーズに来たなら、chart-kit の制限を無理に回避し続けるより、Victory Native に移行した方が開発全体のペースが上がることが多いです。
chart-kit でMVPを作って、必要になったら乗り換えるというアプローチは十分に合理的です。ただ、乗り換えに1日以上かけるような段階になったら、移行コストよりも「早めに切り替えておく方がよかった」という後悔の方が大きくなりがちです。
Rork でデータ可視化機能を本格的に作り込む予定があるなら、最初から Victory Native で設計しておくことをおすすめします。インタラクション(タップでツールチップ表示など)やアニメーションを後から加える際も、Victory Native の方がはるかにスムーズです。