vega / react-vega

Convert Vega spec into React class conveniently
http://vega.github.io/react-vega/
Other
373 stars 67 forks source link

Will the VegaLite component re-render on spec change? #598

Open claresloggett opened 1 year ago

claresloggett commented 1 year ago

This is (I think) a question rather than a bug report.

I've currently got a setup where I'd like to be able to modify the spec and the data on the fly. So I have something like

const [spec, setSpec] = useState<TopLevelSpec | null>(null)
const [data, setData] = useState([])

return (
<VegaLite spec={spec} data={{inputdata: data}}/>
)

This is obviously a snippet cut out of the code, but hopefully gives the idea.

If I call setSpec() during runtime, I can observe that the state has really changed (I can trigger a useEffect hook that's dependent on spec), but the plot does not re-render to use the new spec. Should it? If not, what's the right way to cause the VegaLite component to re-render?

paulrosenzweig commented 1 year ago

The visualization should update when the spec prop is changed. Here's a simple example where you can click a button to update the bar color.

Do you have a self-contained example where that isn't happening? It seems like it's a bug.

import React, { useState } from 'react';
import { VegaLite } from 'react-vega';

const initialSpec = {
  mark: 'bar',
  encoding: {
    x: { field: 'category', type: 'nominal' },
    y: { field: 'value', type: 'quantitative' },
  },
  data: {
    values: [
          { category: 'A', value: 1 },
          { category: 'B', value: 2 },
          { category: 'C', value: 3 },
    ]
  },
};

const rand256 = () => Math.floor(Math.random() * 256);

const App = () => {
  const [spec, setSpec] = useState(initialSpec);

  const updateSpec = () => {
    const updatedSpec = JSON.parse(JSON.stringify(initialSpec));
    updatedSpec.encoding.color = {value: `rgb(${rand256()}, ${rand256()}, ${rand256()})`};
    setSpec(updatedSpec);
  };

  return (
    <div>
      <button onClick={updateSpec}>Update color</button>
      <VegaLite spec={spec} />
    </div>
  );
};

export default App;