title: Really need some help figuring out the logic of componentWillMount() prior to render
body: <p>this might be kind of long read, I've read and tried so many solutions without success! Essentially what I have is three MySQL tables, one with a list of users, and one with a list of file data. They are paired with a third table, which has a column for user id and a column for file id.</p>
  
  <p>When a user logs into the app, it grabs their ID from Table 1, goes to Table 3, finds all the file IDs that are in the same row as their user ID, and then returns the file information from Table 2. Mostly straight forward, except it's not.</p>
  
  <p>My current code:</p>
  
  <pre><code>componentWillMount() {
      this.getClientFiles();
  }
  </code></pre>
  
  <p>Which calls:</p>
  
  <pre><code>getClientFiles() {
          let id = this.props.currentUser.user_id;
          let file_refs = [];
  
          axios.get(`/users/get-client-files/${id}`)
            .then(res =&gt; {
              let response = res.data.response;
  
              for (let i = 0; i &lt; response.length; i++) {
                  file_refs.push(response[i].file_id);
              }
              this.setState({
                  file_refs
              });
              this.getFileData();
          });
      }
  </code></pre>
  
  <p>My understanding of this is that <code>this.getFileData();</code> should ONLY run once the axios GET request is successful (because of <code>.then</code>). The file refs are all returned, and the added to an array and put in state for the duration of the client's session. </p>
  
  <p>Then this should run:</p>
  
  <pre><code>getFileData() {
      let fileRefs = this.state.file_refs;
      let fileData = [];
  
      for (let i = 0; i &lt; fileRefs.length; i++) {
          axios
              .get("/files/get-file/" + fileRefs[i])
              .then(res =&gt; {
                  fileData.push(res.data.response);
                  this.setState({
                      client_files: fileData,
                      returned_data: true
                  });
              })
              .catch(err =&gt; console.log(err.response.data));
      }
  }
  </code></pre>
  
  <p>Here, the function cycles through the fileRefs in state, makes a call for each reference ID, and returns that to fileData and saves it to state. </p>
  
  <p>The problem.... on first page load after a login, the files do not render. If you hit cmd+R to refresh, boom there they are. I understand the chain of promises, and the async nature of JS functions, I understand that <code>componentWillMount()</code> should run prior to the mounting of the component, and that <code>setState</code> should trigger a re-render of a component. </p>
  
  <p>Things I've tried:
  1) Adding the following code in after <code>render()</code> prior to <code>return(</code> :</p>
  
  <pre><code>    if (this.state.returned_data === false) {
          this.getClientFiles();
      }
  </code></pre>
  
  <p>The result is a flickering of renders, 4-5 of them, as the functions run async before the state of returned_data is set to true.</p>
  
  <p>2) Moving the <code>setState({ returned_data: true })</code> into the <code>getClientFiles()</code> function. This just ends the render early, resulting in no files until the page is refreshed.</p>
  
  <p>3) Swapping out <code>componentWillMount()</code> for <code>componentDidMount()</code>.</p>
  
  <p>Clearly, there is a fundamental aspect of the chain of functions and React's built in methods that I'm missing.</p>
  
  <p>Can anybody help?</p>
  
  <p>EDIT #1
  The issue seems to be that on first render, <code>let id = this.props.currentUser.user_id;</code> is <code>undefined</code>, so the call in <code>getClientFiles</code> is actually going to <code>/users/get-client-files/undefined</code></p>
  
  <p>EDIT #2 - Requested by @devserkan
  I hope this is what you wanted :)</p>
  
  <p>First load
  <code>get-client-files/${id}</code>: Returns an empty array
  <code>/get-file/" + fileRefs[i]</code>: Doesn't run</p>
  
  <p>Second load: 
  <code>get-client-files/${id}</code>: Returns array with 5 items
  <code>/get-file/" + fileRefs[i]</code>: Runs appropriately 5 times with the details of each file.</p>
  
  <p>So clearly, the issue is with the fact that <code>get-client-files/${id}</code> isn't getting anything because it doesn't have the <code>${id}</code> to search from. The ID is passed down via props, but doesn't seem to be available immediately.</p>
  
  <p>EDIT #3
  Here is the function that gets the ID, and sets it to state.</p>
  
  <pre><code>getUser = () =&gt; {
      let localToken = localStorage.getItem("iod_tkn");
  
      axios({
          url: "/admins/current",
          method: "get",
          headers: {
              Authorization: localToken
          }
      })
          .then(result =&gt; {
              this.setState({
                  isLoggedIn: true,
                  user: result.data,
                  user_id: result.data.user_id
              });
          })
          .catch(err =&gt; {
              this.setState({ isLoggedIn: false });
              console.log(err);
          });
  };
  </code></pre>
  
  <p>And App.js renders the following:</p>
  
  <pre><code>render() {
      const { loading } = this.state;
  
      if (loading) {
          return &lt;Spinner /&gt;;
      }
  
      return (
              &lt;AdminProvider&gt;
                  &lt;FileProvider&gt;
                      &lt;Provider&gt;
                          &lt;Appbar isLoggedIn={this.state.isLoggedIn} logout={this.logout} /&gt;
                          &lt;Main
                              getUser={this.getUser}
                              isLoggedIn={this.state.isLoggedIn}
                              currentUser={this.state.user}
                          /&gt;
                          &lt;BottomNav /&gt;
                      &lt;/Provider&gt;
                  &lt;/FileProvider&gt;
              &lt;/AdminProvider&gt;
  
      );
  }
  </code></pre>
  
  <p>So with passing <code>this.state.user</code> into Main.js, that component should re-render once the props have been received, right? </p>