2

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?

5
  • It is not clear what you're trying to do. Why are you using a loop ? Do you need to call this.loadData() multiple times or are you using it to wait until the data was loaded ? Commented May 11, 2018 at 20:49
  • How is newElement being used? I assume it's not repeatedly fetching data while the state isn't set... Commented May 11, 2018 at 20:51
  • I have nested components (recrusive calls). If i create a new element 5 levels down from the main element (where the above functions are), i tell the server there, and i pass with the props all the way up to the main element to call the function newElement. But it gets called before the server process the new element. And all the elements fetched in loadData. So i use the loop to fetch again and again until the function detects the change in the received data's length. Commented May 11, 2018 at 20:55
  • 1
    so newElement will be passed as a prop to the child component ? can you add you full component code here so that it can be easy view what exactly you are trying to achieve. m pretty sure you will not need to use do-while loop here. Commented May 11, 2018 at 20:57
  • sounds like you possibly need a async/await inside newElement that waits for the return of loadData but it's hard to tell, the question and code are not clear. Commented May 11, 2018 at 20:59

2 Answers 2

1

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))
  }
Sign up to request clarification or add additional context in comments.

Comments

0

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>
    );
  }
}

Comments

Your Answer

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