Seaky
Seaky

Reputation: 249

unable to find a React.Component by id

I have a React.Component with render() declared this way:

render(){
    return <div>
        <button id="butt" onClick={()=> $("#noti").change("test") }>click me</button>
        <Notification id="noti" onMounted={() => console.log("test")}/>
    </div>
}

And this is my Notification class:

class Notification extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            message: "place holder",
            visible: false
        }
    }

    show(message, duration){
        console.log("show")
        this.setState({visible: true, message})
        setTimeout(() => {
            this.setState({visible: false})
        }, duration)
    }

    change(message){
        this.setState({message})
    }

    render() {
      const {visible, message} = this.state
      return <div>
          {visible ? message : ""}
      </div>
    }
  }

As the class name suggests, I am trying to create a simple notification with message. And I want to simply display the notification by calling noti.show(message, duration).

However, when I try to find noti by doing window.noti, $("#noti") and document.findElementById("noti"), they all give me undefined, while noti is displayed properly. And I can find the butt using the code to find noti.

How should I find the noti? I am new to front end so please be a little bit more specific on explaining.

Upvotes: 1

Views: 2046

Answers (5)

meenu
meenu

Reputation: 11

I have hardcoded the id to 'noti' in the render method. You can also use the prop id in the Notification component.I have remodelled the component so that you can achieve the intended functionality through React way.

    class App extends React.Component {

      constructor(props) {
        super(props);
        this.state = {
          messageContent: 'placeholder'
        }
      }

      setMessage = (data) => {
        this.setState({messageContent : data});
      }

      render() {

        return (
          <div className="App">
            <button id='butt' onClick= {() => this.setMessage('test')} />
            <Notification message = {this.state.messageContent} />
          </div>
        );
      }

    }

    class Notification extends React.Component {

      render () {
        const {message} = this.props;
        return (
          <div id='noti'>
            {message}
          </div>
        )
      }

    }

Upvotes: 1

devserkan
devserkan

Reputation: 17608

This answer does not provide the exact answer about selecting a component as you want. I'm providing this answer so you can see other alternatives (more React way maybe) and improve it according to your needs.

class App extends React.Component {
  state = {
    isNotiVisible: false
  };

  handleClick = () => this.setState({ isNotiVisible: true });

  render() {
    return (
      <div>
        <button onClick={this.handleClick}>Show Noti</button>
        {this.state.isNotiVisible && (
          <Noti duration={2000} message="This is a simple notification." />
        )}
      </div>
    );
  }
}

class Noti extends React.Component {
  state = {
    visible: true
  };

  componentDidMount() {
    setTimeout(() => this.setState({ visible: false }), this.props.duration);
  }

  render() {
    return this.state.visible && <div>{this.props.message}</div>;
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />

Upvotes: 0

Gaurav
Gaurav

Reputation: 2018

You can't pass id/class to a React Component as you would declare them in your normal HTML. any property when passed to a React Component becomes a props of that component which you have to use in the component class/function.

render() {
      const {visible, message} = this.state
      // give your id props to div tag as id attr
      return <div id={this.props.id}>
          {message}
      </div>
    }

Upvotes: 0

alpay
alpay

Reputation: 618

Before beginning: Using id/class to reach DOM nodes is not suggested in React.js, you need to use Ref's. Read more at here.


In your first render method, you give id property to Notification component. In react.js,

if you pass a property to some component, it becomes a props of that component. (read more here)

After you give the id to Notification, you need to take and use that specific props in your Notification component.

You see that you inserted a code line super(props) in constructor of Notification? That means, take all the props from super (upper) class and inherit them in this class.

Since id is HTML tag, you can use it like:

class Notification extends React.Component {
    constructor(props) {
        // inherit all props from upper class
        super(props);
        this.state = {
            message: "place holder",
            visible: false,
            // you can reach all props with using this.props
            // we took id props and assign it to some property in component state
            id: this.props.id
        }
    }

    show(message, duration){
       // code..
    }

    change(message){
       // code..
    }

    render() {
      const {visible, message, id} = this.state
      // give that id to div tag
      return <div id={id}>
          {message}
      </div>
    }
}

Upvotes: 0

Alireza Esfahani
Alireza Esfahani

Reputation: 741

It's not a good idea using JQuery library with Reactjs. instead you can find a appropriate react library for notification or anything else.

Also In React we use ref to to access DOM nodes. Something like this:

    constructor(props) {
        super(props);
        this.noti = React.createRef();
    }

    ...

    <Notification ref={this.noti} onMounted={() => console.log("test")}/>

more info: https://reactjs.org/docs/refs-and-the-dom.html

Upvotes: 5

Related Questions