user9686855
user9686855

Reputation:

How to detect if state was changed? reactjs

I have this code:

class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      elements: [],
    }
  }
  loadData = () => {
    fetch('http://localhost:3001/')
    .then(res => res.json())
    .then(data => {this.setState({elements: data})})
    .catch(err => console.log(err))
  }
    newElement = () => {
    do {this.loadData()} while (/don't know what to put here/ === this.state.elements.length)


  componentDidMount(){
    this.loadData();
    console.log(this.state.feladatok)

  }
  render() {
    return (
      <div className="App">
        <Element newElem={() => this.newElement()}/>
      </div>
    );
  }
}

//The Element component renders more Element components. All element component looks like this inside:
//<Element newElem={this.props.newelem} />
//If a new element has created, that will do two things:
//Adds a new element to the database
//The this.props.newElem() gets called

The situation is that the newElement is called from the children component's props just if a new component was created (and posted to the database). I need to wait until the server responds with the new data. The data comes as an array. (approximately 10ms, but i think it's better to wait the time). The code shown above is my idea to detect if the elements length isn't the same it was before. But if i create a new state, for an example elementsCounter(and set the empty value to 0), whatever where i set it to elements.length, it still remains 0. Or if i declare a variable into the newElement function, and set the value to this.state.elements.length, and after do the do...while, it creates an infinite loop. So how to solve this problem?

Upvotes: 2

Views: 5515

Answers (2)

Pranay Tripathi
Pranay Tripathi

Reputation: 1882

You might have to use a boolean flag which tells you whether your data is loaded or not. You also should show some kind of loading on the screen so that the user is aware that some thing is happening behind the scene. So with the new state flag your code would look something similar to this:

class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      elements: [],
      dataLoaded: false,
    }
  }
  loadData = () => {
    fetch('http://localhost:3001/')
    .then(res => res.json())
    .then(data => {this.setState({elements: data, dataLoaded: true })})
    .catch(err => console.log(err))
  }
    newElement = () => {
        this.setState({dataLoaded: false}, () => {
            this.loadData();
        })
    }

  componentDidMount(){
    this.loadData();
    console.log(this.state.feladatok)

  }
  render() {
    return (
      dataLoaded ? <div className="App">
        <Element newElem={() => this.newElement()}/>
      </div> : <div>Loading......</div>
    );
  }
}

Upvotes: 0

Titus
Titus

Reputation: 22474

You can use recursion instead of a loop.

Here is an example:

loadData = () => {
    fetch('http://localhost:3001/')
    .then(res => res.json())
    .then(data => {
        this.setState(prevState => {
           if(prevState.elements.length === data.elements.length){
               // New element not retrieved, try again.
               this.loadData();
           }
           return {elements: data}
        });
    })
    .catch(err => console.log(err))
  }

Upvotes: 1

Related Questions