Reactor
Reactor

Reputation: 63

React- createRef() Api - this.child.current is null

In order to allow my parent component (JsonFetcher) to access values from my child component (Display), I tried using createRef() API that just came of this patch 16.3

Following the "Adding a Ref to a class Component" example in this document, here's what I tried in my code:

class JsonFetcher extends Component {
    constructor(props) {
        super(props);
        this.child = React.createRef();
        this.state = {
            data: [],
        }
    }

    componentDidMount() {   
        this.updateContent(this.props.mainUrl)
    }

    updateContent(mainUrl){
        fetch(mainUrl)
            .then((responseJsonAnyUrl) => responseJsonAnyUrl.json())
            .then((responseJsonAnyUrl) => {
                this.setState({
                    mainUrl: mainUrl,
                    jsonObject: responseJsonAnyUrl
                },
                function () {
                    this.timeout = setTimeout(
                        function(){
                            //let ind = this.child.current.getCurrentIndex
                            //tyring to get values from child...
                            //if index === length-1
                                this.updateContent(mainUrl)
                            //else    
                            //retry this function in 5 seconds
                            // 
                        }.bind(this, mainUrl)
                        ,
                        20000)
                }.bind(this))
            })
    }

    interpretJson() {
        /*
        *some code
        */            
        return(
            <Display content={contentListArray} ref={this.child}/>
        )
    }

    render() {
        if(this.state.jsonObject){
            return (
                <div>
                    <div> {this.interpretJson()} </div>
                </div>
            )
        }else
            return(
                null
            )                
    }
}

So, I created the ref in the constructor, linked it to the child component Display in the end of interpretJson() method and then i'm trying to use the the child method in my timeOut() function. However I get the following error:

"TypeError: Cannot read property 'getCurrentIndex' of null "

What am I doing wrong that's not letting me call the child methods so I can simulate the pseudo-code I have commented?

(Edit) Notes:

Upvotes: 6

Views: 9249

Answers (2)

Andrei L
Andrei L

Reputation: 3681

I also encountered this issue (I'm using typescript)

private modal = React.createRef<HTMLDivElement>()

// ...

public componentDidMount() {
  console.log(this.modal)
}

// ...

public render() {
// ...
  <div ref={this.modal} className="modal fade"
  // ...

Output. From start is null, then is populated after some little time:

enter image description here

The problem was that in render method I exited early, and ref code was not reached

public render() {
  const { data } = this.state

  // here we return early, ref bellow is not reached
  // and in componentDidmount we can't rely on this.modal.current
  // this.modal.current will be populated only if data is not null
  if (data === null) { return null }

  return (
    <div ref={this.modal} className="modal fade"
    // ...

same problem in example in bellow example
enter image description here

example: https://codesandbox.io/s/ymvxj5pqmx

Upvotes: 0

Gautam Naik
Gautam Naik

Reputation: 9368

Use arrow function to bind this method to the class. This way, the this in this.child will bind to the class component

interpretJson = () => {
    /*
    *some code
    */            
    return(
        <Display content={contentListArray} ref={this.child}/>
    )
}

if the above answer doesn't work then do this

 constructor(props) {
        super(props);
        this.interpretJson = this.interpretJson.bind(this);//bind function to class
        this.child = React.createRef();
        this.state = {
            data: [],
        }

 }
 interpretJson() {
        /*
        *some code
        */            
        return(
            <Display content={contentListArray} ref={this.child}/>
        )
    }

Upvotes: 0

Related Questions