Siqueira
Siqueira

Reputation: 443

How do I rerender the page after changing the state of a state variable?

I am setting the state of a state variable in reactjs when a press a button. I call the following procedure (which is actually being called).

nextSuggestion() {
        console.log(this.state.suggestions_index);
        this.state.suggestions_index = this.state.suggestions_index + 1;
        console.log(this.state.suggestions_index);
    }

The above function is called and the page is not rerendered, even though I have the following componentDidMount():

async componentDidMount(){

        const query = new URLSearchParams(this.props.location.search);

        const token = query.get('token');


        const url = "http://www.mocky.io/v2/" + token;


        this.setState({url_prod: url});    

        const response = await fetch(url);
        const data = await response.json();
        this.setState({produto: data.suggestions[this.state.suggestions_index], loading_produto: false})
        this.setState({alternativas: data.choices, loading_alternativas: false})
        this.setState({atributos: data.suggestions[this.state.suggestions_index].product_data.attributes, loading_atributos: false})

    }

The button is created through this code in render() function:

  if(!this.state.loading_alternativas){

    this.texts = lista_alternativas.map((text, key) => {


        return  <div id="center-button"><button type="button" className="btn btn-primary" key={text.id} onClick={this.nextSuggestion.bind(this)}>{text.text}</button></div>
    });
}

the state:

state = {
        produto: null,
        alternativas: null,
        atributos: [],
        suggestions_index: 0,
        loading_produto: true,
        loading_alternativas: true,
        loading_atributos: true,
        showPopupDescProd: false,
        showPopupAnswer: false,
        url_prod: null,
    };

What am I missing to make it work?

Upvotes: 0

Views: 123

Answers (1)

David
David

Reputation: 218828

You're mutating state:

this.state.suggestions_index = this.state.suggestions_index + 1;

Which is a bad thing. More specifically, it's not expected by the ReactJS framework so it has no reason to re-render.

Don't set state values directly. Update the state with a new state object. For example:

this.setState((prevState) => ({
    suggestions_index: prevState.suggestions_index + 1
}));

Calling setState() with notify the framework to replace the current state with the new one, triggering a re-render where applicable.


Edit: In response to Andy's comment (from which I learned something new, thanks Andy!), note also that setState() is asynchronous in nature. Since you're looking to log to the console after setting the state, you'd want to do that in a callback. For example:

const newState = {
    ...this.state
    suggestions_index: this.state.suggestions_index + 1
};
this.setState(newState, () => console.log(this.state.suggestions_index));

(Though I suspect your console.log use is temporary for debugging only and will probably which removed, so you'd just omit the callback.)

Upvotes: 4

Related Questions