Andrew Torr
Andrew Torr

Reputation: 1137

What constitutes an appropriate use of ref in React

Can someone explain how ref is used in React? I understand it's a shortcut that sort of defeats the purpose of the react DOM, but I don't know how or why exactly. I'm trying to determine whether something I'm trying to accomplish represents one of the rare cases where you should use ref

I want a custom bootstrap alert I can show from any of these pages, without using JQuery (I have one working with JQuery already)

I have a router that switches between pages, each containing a Layout component with a Page component inside (based on this) Like:

render() {
  return (<Layout ref={layout => (this.layout = layout)}>
    <WhateverPage
      session={this.session}
      otherExampleProp={"something"}
      showAlert={this.showAlert}/>
  </Layout>);
}

showAlert(type, text, hasTimeout, timeoutMs) {
  this.layout.alert.showAlert(type, text, hasTimeout, timeoutMs);
}

I can think of three solutions:

  1. Use ref, which as I only partially understand defeats the purpose of react components to some extent, but I'm not sure how exactly...

  2. Use ref, but to a lesser extent, by placing the alert component in each Layout before the Page component (so no need for a ref to ).

  3. Create a component and a function on each page, using the page's state to control the alert, so it would be basically the same as creating a unique alert for each page, which also defeats the purpose of a component...

The example most people give when explaining what to use ref for involves focus() - is this similar? Intuitively it feels like I should use ref, but I also know that theoretically you shouldn't, but I want to understand why, because there are exceptions and for all I know this may count.

Similarly, I want to create a confirm component to replace the native JS confirm() (since it might be deprecated soon), and this approach (using ref) also makes this WAY easier than creating a component for each page, since I can pass any function as a parameter to the confirm component for it to execute on an OK button press (also gives me the option of including icons, titles, custom buttons, etc).

Existing examples and libraries all seem to use method 3 (or they're simpler, and not not really analogous).

Is ref ok to use here? Is it wrong? Why? Am I overthinking this?

Upvotes: 1

Views: 253

Answers (2)

Topicus
Topicus

Reputation: 1404

To complement the jered answer:

If you plan to use the alert component in all the pages then instead of placing an alert component inside each page you can create a high order component named like PageWithAlert (I would say just Page) that includes the alert component for each page.

You might want to take a look at this https://facebook.github.io/react/docs/higher-order-components.html

Upvotes: 0

jered
jered

Reputation: 11581

Yes, you are "misusing" ref here because you're trying to build around how React is intended to be used.

ref is mainly for accessing the actual rendered DOM element - maybe to focus it, read input, get dimensions, whatever. Generally speaking though you should us ref as a "read only" feature - use it to get info about the rendered DOM but don't use it as part of a process to bypass render() or inject elements into the DOM.

What you should do is create a reusable component for your Alert. Make it flexible enough that it can accept arbitrary settings like color, text, duration, callback functions for accept/cancel/clear, etc. Then you can just render it somewhere, maybe like this:

<MyAlert
    title="foo"
    text="bar"
    duration={5}
    confirmCallback={someFunction}
    cancelCallback={anotherFunction}
/>

Remember that components are a way to render and interact with state, and that's exactly what you're trying to do with your Alert. There is some kind of notification, it has content and controls for doing some action(s), and all of that should live somewhere in your app state hierarchy. There is absolutely no reason to resort to refin this situation.

Upvotes: 2

Related Questions