prop-types is used for validating the properties are what they are supposed to be. This is invaluable for speed in development. In a nutshell, you should get used to the idea of declaring what the valid types for your properties are (string, array, number, etc)
You will need react and thunk if you want to create a Redux tree of data. You will have to learn how to do fun things like mapStateToProps and mapDispatchToProps, and then you will have a giant data tree that will be mapped to your react components.
Query string will check those query parameters (like ?search or ?utm_campaign, etc) to let you grab them from the browser’s URL.
• react-helmet You use React helmet if you want to set the page’s HEAD tags, for example, if you want unique meta or content tags to be generated depending on what is on the page.
With these you do fun things like unit testing, watching all your specs as you develop, and run a coverage report of how many lines of code you have covered.
This is what you use if you want to integration testing. You’ll note that Cypress is written in jQuery, ironically, because you aren’t supposed to use jQuery with React.
React’s Virtual DOM arguably revolutionized web development. In short: React will keep a copy of the DOM in its own memory space. When you make updates, for example, several updates to component state, the React will manipulate the Virtual DOM first, performing all of the mutations on it in succession. Once all of your logic has run, React knows how to compare the Virtual DOM to the real DOM, and then it makes small, isolated updates one-by-one, only changing the least amount necessary.
Why does it do this? Well, for one thing, when the browser performs DOM operations it is famously slow at doing so, that is non-performant when many updates are happening. If each mutation of the DOM was done in the browser, you couldn’t achieve the fast effects you can with React.
You’ll note then that the objects you code in React, then, don’t expose direct access to the DOM elements. This is a good thing, because it means that to change the DOM you must always go through the React re-render cycle when you want to change your DOM.
Most of the time, this can get you most of what you need doing. But occasionally, if you need to access DOM elements to inspect them, you’ll want to use a feature of React called React Refs.
Other cases of using Refs is to manage text highlighting, managing focus, and media playback. Refs are also used for some advanced purposes too, like managing interactions with 3rd parties and multistep form state.
Today I will explore three patterns for using Refs in React: 1) A basic Ref implementation, 2) A forwarded Ref, that is a ref that has been sent to another component, and 3) A forwarded Ref used within a Styled Components setup.
Remember, your Ref will simply point to the DOM elements. What’s important here to keep in mind is that you 1) first need to create your ref, 2) then assign it to a component using ref= , and 3) let React maintain the Ref for you during the rendering.
Example #1 — Basic Usage
First, you need to create a Ref object. You do this before your component is rendered using React.createRef()
First let’s start with the most basic React component. (To see this, edit your App.js file and remove the default content and add <ThingOne />)
Notice that in the constructor, we create the Ref using this.ref1 = React.createRef(). At this point, if you examine your object, you will see something interestingly empty:
Notice that your variable now holds an object with a single key, current, that points to nothing (null).
Now, let’s add an input checkbox and also tell React to use this ref (ref1) for that input checkbox.
import React from 'react'
class ThingOne extends React.Component{
constructor(props) {
super(props)
this.ref1 = React.createRef()
}
render() {
return (
<div>
this is an experiment into forwarded refs
<br />
Please check this box: <input type={"checkbox"} ref={this.ref1} />
</div>
)
}
}
export default ThingOne
We use this Ref (ref1) in the render method, when we call
<input type={"checkbox"} ref={this.ref1} />
Here, we’re telling React when it renders the dom, a reference will be stored back onto the value in the current slot in our Ref.
If you examine the Ref after React has rendered, you get something different:
Now, the Ref’s current value is a reference to the DOM element. That means that it can be treated like a “native DOM element” because it is one.
Finally, in our little baby example, we’ll attach an onClick handler to the boxChecked handler.
import React from 'react'
class ThingOne extends React.Component{
constructor(props) {
super(props)
this.ref1 = React.createRef()
// if you don't bind your method then boxChecked will be called
// without `this` in scope
this.boxChecked = this.boxChecked.bind(this)
}
boxChecked(event) {
const dom_elem = this.ref1.current
const is_checked = dom_elem.checked
alert("This box is now " + (is_checked ? 'CHECKED' : 'UNCHECKED'))
}
render() {
return (
<div>
this is an experiment into forwarded refs
<br />
Please check this box:
<input type={"checkbox"} ref={this.ref1} onClick={this.boxChecked} />
</div>
)
}
}
export default ThingOne
Be sure to bind it to the this object (because, err.. javascript) in the constructor, and Bob’s your uncle… once clicked, this.ref1.current now returns {current: input} as you see above. As you can see from the code in boxChecked, you can pull the DOM element out from this.ref1.current and then examine it using native HTML properties (.clicked is implemented in the browser and is a native DOM element property.)
Now it’s time to go down the rabbit hole a little deeper. And with ref forwarding, we really are traveling down a rabbit hole. Let’s stay we want to nest ThingTwo inside of ThingOne, but be able to look at the ref for ThingTwo from code inside of ThingOne.
Let’s say we try something like this
// src/thing_one.js
import React from 'react' import ThingTwo from './thing_two'
class ThingOne extends React.Component{ constructor(props) { super(props) this.ref1 = React.createRef()
// if you don't bind your method then boxChecked will be called // without `this` in scope this.boxChecked = this.boxChecked.bind(this) } boxChecked(event) { const dom_elem = this.ref1.current alert("ThingTwo is " + dom_elem.getBoundingClientRect()) }
render() { return ( <div style={{position: 'relative', border: 'solid 1px green'}}> this is an experiment into forwarded refs <br /> Please <button onClick={this.boxChecked} type="button" > click here </button>
<ThingTwo ref={this.ref1}/> </div> ) } }
export default ThingOne
// src/thing_two.js
import React from 'react'
class ThingTwo extends React.Component{
render() { return ( <div style={{position: 'relative', top: 0, left: 0, border: 'solid 1px red'}}> This is thing Two </div> ) } }
export default ThingTwo
Warning: The above code doesn’t actually work!
It makes sense that we might think we can pass a ref as a prop from one component to another. However, because of how React passes props around, this doesn’t actually work. Moreso, it actually produces no error message or indication to the developer that this is wrong. But here’s how you know it’s wrong: If you examine the ref once the UI is rendered, you get this wrong result:
If you see the name of the Component, something is wrong. it won’t work and your ref will not be usable. What’s wrong here is that you need to forward your ref from one component to another.
Interestingly, the code in thing_one.js doesn’t change — you’re still going to pass the ref down to ThingTwo via the props.
However, for ThingTwo, you need to wrap ThingTwo’s entire implementation in React.forwardRef. This utility method will take a function and will call that function with two arguments: the props passed and the ref passed, but it will allow you to pipe the ref into ThingTwo like so:
import React from 'react'
class ThingTwo extends React.Component{
render() {
const {selfRef} = this.props
return (
<div ref={selfRef} style={{position: 'relative', top: 0, left: 0, border: 'solid 1px red'}}>
This is thing Two
</div>
)
}
}
export default React.forwardRef((props, ref) => <ThingTwo {...props} selfRef={ref} />)
Many examples online use a pattern like ref={ref} but I personally find this confusing for demonstration. What is happening is that one variable name exists in the ForwadedRef constructor, and a distinct variable also named ref then also exists inside your component, they just happen to both be called ‘ref.’ To eliminate the confusion, I named the ref that ThingTwo receives selfRef, indicating that this variable is only ever used as the reference to DOM element that maps to the component (to ‘itself’). You can pick any variable names you want, but this example demonstrates that the variable occupies a distinct namespace in ThingTwo.
Now, if you examine your ref after rendering, it looks like so:
Note that in some cases your DOM element object looks slightly different. For example, if React renders multiple of the same component, it will keep letter-based class names on your objects (it does this as its internal mapping to the DOM).
Here’s an example from a different app (you aren’t seeing the code for this). In this case, my component has a built-in class for logo-container and the strange-looking characters that make up the other classes are correct.
The example code for example #2 can be found here.
Example 3 — With Ref Forwarding in a Styled Component
Forwarding refs is slightly tricky. Once you get the hang of it, it makes sense. Always remember that the receiving component must be wrapped in the forwarder. The final pattern to show you here is how a ForwardedRef can be used with Styled Components.
This example is just like #2, except that ThingTwo uses a StyledThingTwo to display itself
You will note that because StyledThingTwo is a functional styled component, it doesn’t need its own forwarded ref wrapper. Only the ThingTwo needs to be wrapped in the forwardRef call.
This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.