Search code examples
javascriptreactjsonchangeonblur

ReactJS - How to get onFocus and onBlur to work


As I understand it, onFocus should be called when the input box is clicked into, and onBlur should be called when something else becomes the focus.

My intentions: I would like to call a function that, when activated by a click, it will .concat the message string of the input box in focuse, but I can't get the onFocus or onBlur to work.

From what I've found searching around, this should do the trick, but doesn't.

import React, { Component } from 'react'
class SocialPost extends Component {
    state = {
        message: this.props.socialPost.message,
        focus: false
    }
    _onBlur() {
        setTimeout(() => {
            if (this.state.focus) {
                this.setState({
                    focus: false,
                });
            }
        }, 0);
    }
    _onFocus() {
        if (!this.state.focus) {
            this.setState({
                focus: true,
            });
        }
    }
    render() {
        return (
            <div className='...'>
                <div className='...'>
                    ...
                    <input
                        onFocus={this._onFocus()}
                        onBlur={this._onBlur()}
                        type='text'
                        value={this.state.message}
                        onChange={...}/>
                    ...
                </div>
            </div>
        )
    }
}
export default SocialPost
  1. Why is onFocus and onBlur called when the component is rendered before I click/unclick them?
  2. How do I get this onFocus and onBlur to work, is is there another way to focus on the activated input box?

Solution

    1. It is called because you run the function in the render method, you should pass function, not what they return.

    Change this:

    onFocus={this._onFocus()}
    onBlur={this._onBlur()}
    

    to this:

    onFocus={this._onFocus}
    onBlur={this._onBlur}
    

    2.You cannot declare component's state like that. It has to be done in constructor. Also if you want to refer to SocialPost's this you have to bind it. Imo the best place to do it is in the constructor. The whole code should look like this:

    import React, { Component } from 'react'
    class SocialPost extends Component {
        constructor (props) {
          super(props)
          this.state = {
            message: props.socialPost.message,
            focus: false
          }
    
          this._onBlur = this._onBlur.bind(this)
          this._onFocus = this._onFocus.bind(this)
        }
        _onBlur() {
            setTimeout(() => {
                if (this.state.focus) {
                    this.setState({
                        focus: false,
                    });
                }
            }, 0);
        }
        _onFocus() {
            if (!this.state.focus) {
                this.setState({
                    focus: true,
                });
            }
        }
        render() {
            return (
                <div className='...'>
                    <div className='...'>
                        ...
                        <input
                            onFocus={this._onFocus}
                            onBlur={this._onBlur}
                            type='text'
                            value={this.state.message}
                            onChange={...}/>
                        ...
                    </div>
                </div>
            )
        }
    }
    export default SocialPost