title: React JS reduce API calls in function
body: <p>As you can see, I am calling my API 3 times. Once in componentDidMount, twice in each functions. How do I reduce the number of API calls to only once, in componentDidMount(), to make the code more efficient?</p>
  <p>This is a simple calling from an API that generates a list, and I am doing a <strong>Category dropdown</strong> and <strong>Search field</strong> that works with the list.</p>
  <p>I imagined that something from the functions need to be moved elsewhere for it to work. Any idea?</p>
  <pre><code>constructor(props){
          super(props);
          this.state = {
              items: [],
              isLoaded: false,
          }
  
          this.ChangeCategory = this.ChangeCategory.bind(this);
          this.btnSearch = this.btnSearch.bind(this);
      }
  
  componentDidMount(){
          fetch('https://examplejson.json')
              //use es6 arrow function to not lose context of 'this'
              .then(res =&gt; res.json())
              .then(json =&gt; {
                  this.setState({
                      isLoaded: true,
                      items: json.response,
                  })
  
                  var items = json.response;
  
                  //Populate category into dropdownlist
                  var select = document.getElementById(&quot;locality&quot;);
                  var options = [];
                  var option = document.createElement('option');
                  var i = 0;
  
                  var uniqueNames = [];
                  for(i = 0; i&lt; items.length; i++){
                      if(uniqueNames.indexOf(items[i].category) === -1){
                          uniqueNames.push(items[i].category);        
                      }        
                  }
  
                  for(i = 0; i&lt; uniqueNames.length; i++){    
                      option.text = option.value = option.key = uniqueNames[i];
                      options.push(option.outerHTML);      
                  }
  
                  select.insertAdjacentHTML('beforeEnd', options.join('\n'));
                  //Populate category into dropdownlist
              }).catch(console.log);
              
      }
  </code></pre>
  <p>My 2 functions</p>
  <pre><code>ChangeCategory(){
          fetch('https://examplejson.json')
          .then(res =&gt; res.json())
          .then(json =&gt; {
              var category;
              var x;
    
              category = json.response;
      
              var result = category.filter((z)=&gt;z.category === document.getElementById(&quot;locality&quot;).value);
  
              var items2 = [];
              for (x in result) {
                  items2[x] = result[x];
              }
  
              this.setState({
                  items: items2,
              })
              
          }).catch(console.log);
  
          document.getElementById(&quot;txtBox1&quot;).value = '';
  
      }
  
  btnSearch(){    
          fetch('https://examplejson.json')
          .then(res =&gt; res.json())
          .then(json =&gt; {
              var items;
              var y;
              var searchItem = [];
  
              items = json.response;
      
              //filter by channel name, search the list with keyword from textbox (don't need to be exact word)
              var result = items.filter((z)=&gt;z.title.toUpperCase().indexOf(document.getElementById(&quot;txtBox1&quot;).value.toUpperCase()) !== -1);
              
              for (y in result) {
                  searchItem[y] = result[y];
              }
      
              this.setState({
                  items: searchItem,
              })
              
          }).catch(console.log);
      
          document.getElementById(&quot;locality&quot;).selectedIndex = 0;
      }
  </code></pre>
  <p>Render</p>
  <pre><code>render() { 
  
          var { isLoaded, items } = this.state;
  
          if(!isLoaded) {
              return &lt;div&gt;Loading...&lt;/div&gt;;
          }
  
          else {
              return (
  
                  
              &lt;div className=&quot;list&quot;&gt;
                  &lt;div className=&quot;row mb-5&quot;&gt;
  
                      &lt;div className=&quot;col-md-6 col-sm-12 category-wrap&quot;&gt;
                          &lt;select key=&quot;locality&quot; id=&quot;locality&quot; className=&quot;form-control&quot; name=&quot;locality&quot; onChange={this.ChangeCategory} style={{padding:&quot;5px&quot;, width:&quot;250px&quot;}}&gt;
                              &lt;option&gt;Select category&lt;/option&gt;
                          &lt;/select&gt;
                      &lt;/div&gt;
  
                      &lt;div className=&quot;col-md-6 col-sm-12 search-wrap&quot;&gt;
                          &lt;div className=&quot;input-group&quot; style={{width:&quot;250px&quot;}}&gt;
                              &lt;input key=&quot;txtBox1&quot; type=&quot;text&quot; id=&quot;txtBox1&quot; className=&quot;form-control&quot; placeholder=&quot;Channel Name&quot; onKeyPress={event =&gt; {
                                  if (event.key === 'Enter') {
                                  this.btnSearch()
                                  }
                              }}/&gt;
                              &lt;button id=&quot;btnClick1&quot; className=&quot;btn&quot; onClick={this.btnSearch}&gt;&lt;i className=&quot;bi bi-search&quot;&gt;&lt;/i&gt;&lt;/button&gt;
                          &lt;/div&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
                  ...
  </code></pre>