0

I've got a simple component that renders a table. The rows are mapped like this:

render () {
    return (
        {this.state.data.map(function(row, i){
            return <Row row={row} key={i}/>
        }.bind(this))}
    )
}

The state is initialized in the constructor:

this.state = {
    data: props.hasOwnProperty('data') ? props.data : [],
    route: props.hasOwnProperty('route') ? props.route : null
}

The data can be initialized in the DOM, or after, the route is passed to the container and bound correctly. In this case, I 'm doing it after in the componentDidMount method:

componentDidMount () {
    axios.get(this.state.route)
        .then(function(resp){
            this.setStateParametersFromAjax(resp);
        }.bind(this))
        .catch(function(err){
            console.log(err);
        })
}

The setStateParametersFromAjax(resp) method is defined here:

this.setState({
    data: resp.data.data,
});

This all works flawlessly on DOM load. However, there are buttons that will perform subsequent requests later on. These requests perform the same axios call.

The problem is, that even though the state is updated (verified by adding a callback as the 2nd argument to the setState method and logging this.state), the DOM does not update.

What do I need to do to make it so that the DOM updates with this new data as well?

Edit

I had simplified the code a bit, there is a method called fetch() that accepts an argument of params that defines the ajax call:

fetch (params) {
    if(typeof params != "object") {
        params = {};
    }
    axios.get(this.state.route, {
            params
        }).then(function(resp) {
            this.setStateParametersFromAjax(resp);
        }.bind(this))
        .catch(function(err){
            console.log(err);
        })
}

The componentDidMount() method calls this on load:

componentDidmMount () {
    this.fetch();
}

When a button is clicked later, this calls a function that calls the fetch method with parameters:

<li className="page-item" onClick={this.getNextPage.bind(this)}>

Where the function is defined:

getNextPage (event) {
    event.preventDefault();

    this.fetch({
        arg: val
    });
}
9
  • You should put your get ajax call in a function and call that after new data is posted. Commented Mar 19, 2017 at 22:37
  • @fungusanthrax See my edits, perhaps I wasn't clear initially. Commented Mar 19, 2017 at 22:40
  • I believe the event parameter may be undefined, which probably should throw an error somehow, which may be the reason the DOM isn't updating. When you call this.getNextPage.bind(this), it doesn't pass an event parameter. So you should use in the onClick onClick={function(event) {event.preventDefault; ...}. Try that... Commented Mar 19, 2017 at 22:51
  • @fungusanthrax It does work correctly. Using .bind(this) differs from passing this.getPreviousPage(this). The first is contextual and the second is an argument and will invoke the function immediately on page load. I know that the fetch etc is all working correctly because, as stated in my question, when I do this.setState({ params...}, function() { console.log(this.state) }). it does show that all of the data is updated. Further, all of the other data returned is updated on the page, just not the rows on the table. Although the this.state does contain the updated rows. Commented Mar 19, 2017 at 22:57
  • maybe use a unique key value other than index. medium.com/@robinpokorny/… Commented Mar 20, 2017 at 6:39

1 Answer 1

1

You should use a unique key value other than index. Even the state is updated, react may not update DOM if the key not changed.

https://facebook.github.io/react/docs/reconciliation.html

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.