2

I'm rendering multiple of the same component, each with their own tooltip. Can I write code that will only look within the HTML of each component, so I'm not affecting all the other tooltips with the same class name? I'm using stateless components. Here is the code:

OptionsComponent.js:

import React from 'react';

const OptionsComponent = () => {
  const toggleTooltip = event => {
    document.getElementsByClassName('listings-table-options-tooltip').classList.toggle('tooltip-hide');
    event.stopPropagation();
  };
  return (
    <div className="inline-block">
        <span onClick={toggleTooltip} className="icon icon-options listings-table-options-icon"> </span>
        <div className="tooltip listings-table-options-tooltip">
            Tooltip content
        </div>
    </div>
  );
};

Backbone.js has something like this, allowing you to scope your document query to begin within the view element (analogous to a React component).

0

4 Answers 4

1

With React, you don't want to modify the DOM. You just re-render your component with new state whenever something happens. In your case, since you want the OptionsComponent to track its own tooltip state, it really isn't even stateless. It is stateful, so make it a component.

It would look something like this:

class OptionsComponent extends React.Component {
  state = {
      hide: false
  };

  toggleTooltip = (ev) => this.setState({ hide: !this.state.hide });

  render() {
      const ttShowHide = this.state.hide ? "tooltip-hide" : "";
      const ttClass = `tooltip listings-table-options-tooltip ${ttShowHide}`;
      return (
        <div className="inline-block">
            <span onClick={this.toggleTooltip} className="icon icon-options listings-table-options-icon"> </span>
            <div className={ttClass}>
                Tooltip content
            </div>
        </div>
      );

      // Alternatively, instead of toggling the tooltip show/hide, just don't render it!
      return (
        <div className="inline-block">
            <span onClick={this.toggleTooltip} className="icon icon-options listings-table-options-icon"> </span>
            {/* do not render the tooltip if hide is true */}
            {!this.state.hide && 
                <div className="tooltip listings-table-options-tooltip">
                    Tooltip content
                </div>
            }
        </div>
      );
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0

You should use refs.

Slightly modified from React docs:

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
  }

  focus() {
    var underlyingDOMNode = this.textInput; // This is your DOM element
    underlyingDOMNode.focus();
  }

  render() {
    // Use the `ref` callback to store a reference to the text input DOM
    // element in this.textInput.
    return (
      <div>
        <input
          type="text"
          ref={(input) => this.textInput = input} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focus}
        />
      </div>
    );
  }
}

Comments

0

A comfortable approach would be modifying your toggleTooltip method this way:

...
  const toggleTooltip = event => {
      event.target.parentNode.querySelector('.tooltip').classList.toggle('tooltip-hide');
  };
...

I would however recommend having a state to represent the tooltip displaying or not.

Comments

0

With https://github.com/fckt/react-layer-stack you can do alike:

import React, { Component } from 'react';
import { Layer, LayerContext } from 'react-layer-stack';
import FixedLayer from './demo/components/FixedLayer';

class Demo extends Component {
  render() {
    return (
      <div>
        <Layer id="lightbox2">{ (_, content) =>
          <FixedLayer style={ { marginRight: '15px', marginBottom: '15px' } }>
            { content }
          </FixedLayer>
        }</Layer>

        <LayerContext id="lightbox2">{({ showMe, hideMe }) => (
            <button onMouseLeave={ hideMe } onMouseMove={ ({ pageX, pageY }) => {
              showMe(
                <div style={{
                      left: pageX, top: pageY + 20, position: "absolute",
                      padding: '10px',
                      background: 'rgba(0,0,0,0.7)', color: '#fff', borderRadius: '5px',
                      boxShadow: '0px 0px 50px 0px rgba(0,0,0,0.60)'}}>
                   “There has to be message triage. If you say three things, you don’t say anything.”
                </div>)
            }}>Yet another button. Move your pointer to it.</button> )}
          </LayerContext>
      </div>
    )
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.