Reputation: 1072
I have a parent component which I'm using to pass props (i.e backgroundColor
) to child component( <LivePortfolioGraph />
).
In my child component I have a dependency array that re-renders every time color is changed from parent i.e (props.backgroundColor
).
Now i don't want want to create a new graph on every render, if chart exist just apply color options.
Really appreciate any help! Thanks.
Parent Component
const Main = (props) => {
const [backgroundColor, setbackgroundColor] = useState('#141d27');
const g = useRef(null);
return (
<div ref={g} className="FinancialChartIntro" >
<LivePortfolioGraph g={g} backgroundColor={backgroundColor} />
</div>
)
}
Child Component
const LivePortfolioGraph = (props) => {
const [width, setWidth] = useState(0);
const [height, setHeight] = useState(0);
useEffect( ()=> {
const handleStyle = _debounce(() => { chart.applyOptions({layout: {backgroundColor:props.backgroundColor } }); }, 100)
window.addEventListener("input", handleStyle);
const chart = createChart(props.g.current, options );
// Clean Up
return () => {
window.removeEventListener('input', handleStyle);
}
}, [props.backgroundColor])
UPDATE I have found a hacky way to remove child nodes( chart dups). It slows down the page like crazy I dont wanna even use it. STILL TRYING to find another solution.
> if(props.g.current.childNodes.length > 2) { > props.g.current.removeChild(props.g.current.childNodes[2]) }
Upvotes: 2
Views: 1391
Reputation: 20885
Using the chart remove() method before any new initialization works for me:
const chartRef = useRef<HTMLDivElement>(null);
const chart = useRef<IChartApiBase>();
useEffect(() => {
if (!chartRef.current) return;
chart.current?.remove();
chart.current = createChart(chartRef.current, {...});
// chart stuff
chart.current.timeScale().fitContent();
}, [chartRef.current, ...dependencies]);
Upvotes: 1
Reputation: 1634
Just perform a check to see if the chart has already be instantiated.
Here is a snippet of a hook I created to setup the chart useSetupChart
useEffect(() => {
if (!chartContainerRef.current || chart) return;
setChart(createChart(chartContainerRef.current));
}, [chartContainerRef.current, chart]);
Upvotes: 1
Reputation: 203227
I think your issue is the single useEffect
hook is doing "too much" work. Move the chart
value into a React ref and use the effect hook to update the color/styling.
const LivePortfolioGraph = (props) => {
const [width, setWidth] = React.useState(0);
const [height, setHeight] = React.useState(0);
const chart = React.useRef(createChart(props.g.current, options);
React.useEffect(()=> {
const handleStyle = _debounce(() => {
chart.current.applyOptions({
layout: {
backgroundColor: props.backgroundColor,
},
});
}, 100);
window.addEventListener("input", handleStyle);
// Clean Up
return () => {
window.removeEventListener('input', handleStyle);
}
}, [props.backgroundColor]);
Upvotes: 1