Instructor: This application renders a bar chart. The bar chart isn't implemented yet, and only rendering an empty SVG element at the moment. To implement it, we want to use the charting library D3. It's a great tool but it needs access to the DOM element. To do so, we can import D3, add a class name to the SVG, and select it using D3 select inside componentDidMount.
While this is possible, this could cause trouble for our whole application further down the road. For example, to avoid problems, we would need to ensure that this is the only class named chart used in our whole application. Not a great idea. How can we fix it?
In the typical React data flow, props are the only way that parent components interact with the children. However, there are a few cases like hours where we need to imperatively modify a child outside of the typical data flow. React therefore provides an escape hatch with so-called refs, allowing us to modify an instance of a React component or a DOM element.
To create a ref, we can use React.createRef in the constructor. In this case, we assign it to this.chartRef. Using ref, we can bind our chart ref to the SVG. In order to access it, we can then use this.chartRef.current. Let's log out ref to get a better understanding of what's happening here.
First, we create the chart ref, but inside the constructor the current property is set to null. The ref is not bound yet. Since render didn't yet run, the changes haven't been committed to the DOM. Once that's done, componentDidMount run and we finally could access the ref. By the way, as an alternative, you also can instantiate the ref directly as a property of this class.
Now that we can access the SVG, let's try a bunch of code to actually render a bar chart. I'm not going to go into detail here, as this isn't the purpose of this lesson. To give you a glimpse of it, we create the X scale function that helps us calculating the width. Then, we add a couple of rectangles and texts for the bars.
Looks good. Previously, I briefly mentioned that we can also ref instances of React components. Let's try this with our bar chart component. We add a function highlight and when invoked it will fade the color of the selector bar to orange and back to steel blue.
In App, we create a ref for the bar chart. Then at a button, use the ref to invoke highlight. Worked as expected and not that complicated after all. What you should know though is that you may not use the ref attribute on functional components simply because they don't have instances. For example, if you have a functional component containing an input, use the ref on it and it will stay null.
Keep in mind, we can use ref for a functional component, but for sure can use refs inside it. For example, here, we create a ref for the input and provide a button that once clicked will switch the focus to the input.
React also provides the callback refs which will continue to be supported in addition to the createRef API. While less convenient, this is likely more flexible in the sense that you have a lot more control.