imran chowdhury
imran chowdhury

Reputation: 398

this.setState is not updating the state property

I am setting the state in a method call from a constructor but the state property is still null. Some modification on the code gives be this error in the console,

index.js:1375 Warning: Can't call setState on a component that is not yet mounted. This is a no-op, but it might indicate a bug in your application. Instead, assign to this.state directly or define a state = {}; class property with the desired state in the ResultContainer component.

In my component constructor i am calling a method. That method in turn calls another method and is trying populate an state property with an array. I get two different variants of error/warning. In my code if uncomment the lines inside render method i get searchedAddress is null error. if i leave the lines as commented then in the console i get the above error.

On my render() method i can check for null and that certainly does not throw and error but the the result items are not getting loaded no matter what i do. this question, State not changing after calling this.setState seems somewhat relevant but i am not sure i could i re-render the item asynchronously.

import React from 'react';
import ResultItem from './ResultItem'
import AddressService from '../Api/AddressService'

class ResultContainer extends React.Component{
    constructor(props){
        super(props);

        this.state = {
            searchedAddresses : null
        }
        this.intiateSearch();        
    }

    intiateSearch =() => {        
        if(this.props.searchedTerm != null){
            var addressService = new AddressService();

            //this is just getting an items from json for now. i checked and result does contain items
            var result = addressService.searchAddress(this.props.searchedAddresses);            

            //the below line does not seem to work
            this.setState({
                searchedAddresses : result
            });            
        }
    }

    render(){
        return(
            <div className="mt-3">
            <h4>Seaching for postcode - <em className="text-primary">{this.props.searchedTerm}</em></h4>

            <div className="container mt-1">
            {  
                //below gives an error stating searchedAddresses is null 
                // this.state.searchedAddresses.map((address, index)=>{
                //     return(<ResultItem address={address}/>);
                // })

            }
            </div>
            </div>
        );
    }

}

export default ResultContainer;

Upvotes: 0

Views: 1022

Answers (2)

Jonathan Beadle
Jonathan Beadle

Reputation: 418

You shouldn't call component functions inside of the constructor method, the component is not yet mounted at this point and therefore your component functions aren't available to be used here yet. In order to update your state. You used to be able to use the componentWillMount lifecycle method but that is now considered legacy. You should be calling any component initializing functions inside of the componentDidMount lifecycle method.

Change your code like so : (Notice the check for state initially being null in the render function)

import React from 'react';
import ResultItem from './ResultItem'
import AddressService from '../Api/AddressService'

class ResultContainer extends React.Component{
constructor(props){
    super(props);

    this.state = {
        searchedAddresses : null
    }      
}

componentDidMount() {
    this.intiateSearch();
}

intiateSearch =() => {        
    if(this.props.searchedTerm != null){
        var addressService = new AddressService();

        //this is just getting an items from json for now. i checked and result does contain items
        var result = addressService.searchAddress(this.props.searchedAddresses);            

        this.setState({
            searchedAddresses : result
        });            
    }
}

render(){
    return(
        <div className="mt-3">
        <h4>Seaching for postcode - <em className="text-primary">{this.props.searchedTerm}</em></h4>

        <div className="container mt-1">
        {  
            this.state.searchedAddresses !== null && 
            this.state.searchedAddresses.map((address, index)=>{
                 return(<ResultItem address={address}/>);
             })

        }
        </div>
        </div>
    );
}

}

export default ResultContainer;

Upvotes: 3

kensong
kensong

Reputation: 247

I see you're calling this.intiateSearch(); in constructor which will call setState on a not yet mounted component. So why don't you call this.intiateSearch(); inside componentDidMount() lifecyle after the component is mounted?

componentDidMount() {
   this.intiateSearch();
}

Upvotes: 2

Related Questions