10

I have a text and a button.

What I want to achieve is something like this, that if I clicked the Button the Text will be hidden. I want to achieve this without using state.

class Test extends Component {
    constructor(props){
        //codes
    }

    hide = () => {
        const span = this.refs.spanLoading;
        span.ClassName = "hidden";
    }

    render() {

        return (
            <span ref="spanLoading" id="test-id" className="">The Quick Brown Fox.</span>

            <button onClick={() => this.hide()}>Hide</button>
        );
    }
}

export default Test;
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
larp
  • 1,017
  • 1
  • 14
  • 23
  • 1
    ref will give you the dom element. You can then use classList attribute of span. You can add hidden class using span.classList.add("hidden") – Juned Lanja Sep 04 '19 at 05:25

3 Answers3

15

You can use useRef() hook.

Maintain one ref object which is not a string.

const {useRef} = React;

function App() {
  const ref = useRef(null);
  const onClick = () => {
    const span = ref.current; // corresponding DOM node
    span.className = "hidden";
  };
  return (
    <div>
      <span ref={ref} className="">The Quick Brown Fox.</span>
      <button onClick={onClick}>Hide</button>
    </div>
  );
}

ReactDOM.render(
  <App />,
  document.getElementById("root")
);
.hidden {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Joseph D.
  • 11,804
  • 3
  • 34
  • 67
  • Okay wait a minute. – larp Sep 04 '19 at 06:36
  • hide = () =>{ const span = this.refs.spanLoading; // I dont know how to call the ref here. span.ClassName = "hidden"; } table = () =>{ tableDetail = Object.keys(postD).map((i) => (

    { postD[i].title }

    { postD[i].content }

    The Quick Brown Fox. --> the ref is like ref="ref-1" and ref="ref-2" and ref="ref-3" so on..
    } render(){ return ( <> {this.table()} > ); }
    – larp Sep 04 '19 at 06:48
1

This can be achieved simply, your approach is correct just some few fixes.

  • You can return only one element in JSX
  • The ref should be maintained somewhere in JS memory

Check this code and the working codesandbox instance here

class Test extends React.Component {
  constructor() {
    super();
    this.inputRef = React.createRef();
  }

  hide = () => {
    console.log(this.inputRef);
    this.inputRef.current.style.visibility="hidden";
  };

  render() {
    return (
      <>
        <span ref={this.inputRef} id="test-id" className="">
          The Quick Brown Fox.
        </span>
        <button onClick={() => this.hide()}>Hide</button>
      </>
    );
  }
}

EDIT! As you asked about dynamically generated refs...

This is what I understood as your requirement... see whether it matches it.

Working sandbox here

class Test extends React.Component {
  constructor() {
    super();
    this.inputRef = React.createRef();
    this.refCollection = {};
    for (let id = 0; id < 10; id++) {
      this.refCollection["id_" + id] = React.createRef();
    }
  }

  hide = e => {
    console.log(this.inputRef);
    this.inputRef.current.style.visibility = "hidden";
  };

  hideInCollection = k => {
    let changedRef = this.refCollection[k];
    changedRef.current.style.visibility = "hidden";
  };
  render() {
    return (
      <>
        <span ref={this.inputRef} id="test-id" className="">
          The Quick Brown Fox.
        </span>

        <button onClick={() => this.hide()}>Hide</button>
        {Object.keys(this.refCollection).map(k => (
          <div>
            <span ref={this.refCollection[k]} id="test-id" className="">
              Looped the Quick Brown Fox
            </span>
            <button onClick={() => this.hideInCollection(k)}>Hide</button>
          </div>
        ))}
      </>
    );
  }
}
Dehan
  • 4,818
  • 1
  • 27
  • 38
-1
class Test extends Component {
    constructor(props){
        this.hide = this.hide.bind(this);
    }

    hide() {
        this.span.classList.add("hidden");
    }    

    render() {

        return (
          <div>
            <span ref={(el) => { this.span = el; }} id="test-id" className="">The Quick Brown Fox.</span>

            <button onClick={this.hide}>Hide</button>
          </div>
        );
    }
}

export default Test;

You should return a single element tho

joseluismurillorios
  • 1,005
  • 6
  • 11