Getting Refs To Sync With Container State
Tags: refs, userefs, react
Published: 2019-09-23 13:20:01

---
title: Getting Refs To Sync With Container State
published: true
tags: refs, userefs, react,
canonical_url: https://stephencharlesweiss.com//2019-09-24/sync-refs-with-container/
---

I was working on a project recently which was using Refs in order to integrate with a third-party library.

My mental model for refs are that they allow you to view into the internal state of a component _without_ tracking it explicitly. In that way, you can use it for calculations and without the overhead of making a component stateful that otherwise doesn’t require state.

My scenario looked something like this: [![Sketch example](https://stephencharlesweiss.com/static/ac14879814a3a6783c89587008e485ce/b9e4f/ref-container.png)](/static/ac14879814a3a6783c89587008e485ce/fdb8e/ref-container.png)

A stateful container with a component that stored business logic wrapping an input.

The goal was to find a way to lift the value of the input up to the top level container _after_ processing it in a wrapper that contained business logic and _without_ storing it in the wrapper as state. I also needed to be able to update the value of the input in certain situations based on business logic considerations.

Here’s a simplified version of what I came up with:

```javascript
import React, { Component } from ‘react’;
import { render } from ‘react-dom’;
import ‘./style.css’;

const WrapperComponent = props => {
  const refContainer = React.useRef({});
  const { onChange } = props;
  const curRef = refContainer.current
  const curRefVal = refContainer.current && refContainer.current.value;
  console.log({ props, refContainer, curRef, curRefVal })

  const businessLogic = (val) => {
    return val.concat(`—modified!`)
  }

  const handleChange = (e) => {

    onChange(businessLogic(e.target.value))
    if(e.target.value.length === 10) {
      refContainer.current.value = businessLogic(e.target.value)
    }
    console.log(refContainer.current.value)
  }
  return (
    <React.Fragment>
      <div> Phone </div>
      <input ref={refContainer} onChange={handleChange} type='tel'></input>
    </React.Fragment>)
}

const App = () => {
  const [value, setValue] = React.useState(null)
  console.log({ value })
  return (<WrapperComponent onChange={setValue} />)

}

render(<App />, document.getElementById(‘root’));
```

Inspecting the console, we can see that this works!

My `input` has a value. My wrapper applies business logic and then passes it through to the container’s `onChange` method.

I can also format the value inside the input and change it when I need — as I did here when I reach a valid 10-digit phone number.

[![A modified ref](https://stephencharlesweiss.com/static/765f987c0fd145a6582d2f10c85917e9/e82b9/ref-modified.png)](/static/765f987c0fd145a6582d2f10c85917e9/e82b9/ref-modified.png)

## <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>Conclusion

I don’t expect to use refs frequently. The React team discourages the practice for one except in certain circumstances (like working with 3rd Party Libraries which was the impetus to this exercise).<sup>1</sup>

Still, learning _how_ I can use them to manage state without re-rendering a component when it changes can be useful, which is exactly what I did here.

Refs also allow you to reach _up_ in React, at least if viewed from a certain perspective, and knowing about that is handy.

NB: I also put this into a Stackblitz if you’re interested in playing around/<sup>2</sup>

## <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>Resources

- <sup>1</sup> [Refs and the DOM | React](https://reactjs.org/docs/refs-and-the-dom.html)
- <sup>2</sup> [refs-in-sync | StackBlitz](https://stackblitz.com/edit/refs-in-sync)