Skip to content

Other frameworks

rhp is built on Solid, but a chart is just elements on the page, so it can live inside an app built with anything else. The idea is the same everywhere:

  1. Give rhp an empty element to draw into.
  2. Keep the chart’s data in a Solid signal, and set it when your app’s data changes.
  3. Clean up when the component goes away.

Your app’s JSX belongs to your framework, so the rows are written with Solid’s html template, as in a plain HTML page. For React there’s a package that does the rest; for other frameworks, @bezda/rhp/standalone has rhp, Solid and html in one import.

React

@bezda/rhp-react turns an rhp chart into a React component:

npm install @bezda/rhp-react
import { useState } from "react";
import { toReact, Chart, Plot, Bar, Label, html } from "@bezda/rhp-react";

const row = (d) => html`
  <div>
    <${Label} edge="start">${() => d.fruit}<//>
    <${Bar} to=${() => d.sold} />
    <${Label} at=${() => d.sold}>${() => d.sold}<//>
  </div>`;

const FruitChart = toReact((props) => html`
  <${Chart} scale=${[0, 30]}>
    <${Plot} fruit=${() => props.fruit} sold=${() => props.sold}>${row}<//>
  <//>`);

export function App() {
  const [sold, setSold] = useState([12, 18, 7]);
  return <FruitChart fruit={["Apples", "Bananas", "Cherries"]} sold={sold} className="card" />;
}
  • props holds the component’s props. Read them inside functions, ${() => props.sold}, so the chart follows them.
  • A change updates only what it touches: a new number in sold moves one bar, as in a Solid app.
  • The component renders a <div> that the chart draws into; className and style go on it.
  • Everything else (the blocks, slat, the helpers, html, createSignal) comes from the same package.

Vue

npm install @bezda/rhp
<script setup>
import { onMounted, onBeforeUnmount, ref, watch } from "vue";
import { Chart, Plot, Bar, html, render, createSignal } from "@bezda/rhp/standalone";

const props = defineProps(["fruit", "sold"]);
const box = ref(null);
const [data, setData] = createSignal({ fruit: props.fruit, sold: props.sold });
let dispose;

onMounted(() => {
  const row = (d) => html`<div><${Bar} to=${() => d.sold} /></div>`;
  dispose = render(() => html`
    <${Chart} scale=${[0, 30]}>
      <${Plot} fruit=${() => data().fruit} sold=${() => data().sold}>${row}<//>
    <//>`, box.value);
});
watch(() => [props.fruit, props.sold], ([fruit, sold]) => setData({ fruit, sold }));
onBeforeUnmount(() => dispose?.());
</script>

<template><div ref="box" /></template>

Svelte, Angular and others

The same three steps apply: draw with render into an element once it’s on the page, set the signal when your data changes, and call the function render returns when the component is removed.