Skip to content

[reactjs] zoom is resetting on render #588

@georgbuechner

Description

@georgbuechner

Hey guys,

in advance: part of the reason, why I'm filing this issue is probably due to my missing knowledge of reactjs and chartjs, and I understand if that is kinda a no-go for you guys, who implemented this great plugin and are maybe annoyed by having to answer questions like this. however I did a lot of googling, but I could not find an answer or a link to the right direction. The only thing that is coming close to the problem I have is this github issue (reactchartjs/react-chartjs-2#107), where OP has the same issue but with a different graph-library

I implemented a Line-Chart in a functional component, and zooming kinda works, but as soon as the component is rendered again, the zoom resets to default (making zoom unusable). Any Idea, how to prevent this behavior?

I have the feeling that one option would be to safe the current zoom and then pass the current zoom to the Chart-Component in the return statement, but a) I would need some help on passing the current or stored zoom to the component, as I couldn't find any instructions on how to do that and b) it seems a bit overkill, that I need to do that, and I was hoping (and expecting) a more straight forward solution.

Here is a code snippet, I can provide the full code, if needed.

export default function HistoryGraph({history, setHistory, ...other}) {
  let { id } = useParams()
 
 const [values, setValues] = useState({
    history: ConvertValues(history);  // extracts the data-rows for each values.
    hidden: history[id].hidden  // hidden (true/ false) is stored for each data-row, to keep it when moving around in the app.
  });
  const chartRef = useRef(null);  // the ref is used to reset zoom, and potentially for adding more buttons (f.e. zoom +10% ...) 
  const [data, setData] = useState({...inital_data});]
  
  // I don't know if I really need the useEffect here. but it should be a problem anyway.
  useEffect(() => {
    let datasets = [...initial_data.datasets];
    for (let i=0; i<datasets.length; i++) {
      datasets[i].data = values.history[datasets[i].label];
      datasets[i].hidden = values.history[datasets[i].hidden];
    }
    let labels = values.history.time;
    setData({labels: labels, datasets: datasets});
  }, [values]);

  // This callback is actually updating the graph. updateHistory is either 
  // called on refresh-button-click or every time when history 
  // is updated, depending on whether life-mode is on/ off.
  const updateHistory = useCallback(() => {  
  setValues({
     history: ConvertValues(history),
     hidden: history[id].hidden,
   });
 }, [id, history]);
  
  const options = {
    plugins: {
      zoom: {
        zoom: {
          wheel: {enabled: true},
          pan: {enabled: true},
          mode: 'xy'
        },
        pan: {enabled: true: mode: 'xy'},
       }
     }
     ...
  };

  const resetZoom = () => { chartRef.current.resetZoom(); }

  return (
    <React.Fragment>
       <Button onClick={resetZoom}>Reset Zoom </Button>
       <Line ref={chartRef} data={data} options={options}/>  // is it possible to pass current zoom to the component here?
    <React.Fragment>
  );
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions