Where to put api call to trigger it every time state changes

Hi everyone, I am new to react. any help is deeply appreciated!

I am using React with TypeScript but it doesn’t have a different behaviour as far as I know, in my case.

My goal is to call api based on state change, Every time state changes, I want the api call triggered.

MyComponent

import * as React from 'react';

export class Verifier extends React.Component<{}, IState> {
  constructor(props: {}) {
    super(props);

    this.state = {
      str: '',
      response: []
    }
  }
verifyIt(myArg) {
  var apiCall = fetch(myApi + 'myArg');

    apiCall.then(response => {
      return response.json();
    }).then(result => {
      console.log(result);
      this.setState({
        response: result
      })
    });
  }

  componentWillMount() {
    let myArg = this.state.myArg;
    this.verifyIt(myArg);
  }

  handleSubmit(e: any) {
    e.preventDefault();
    this.setState({
      myArg: this.state.str
    })
  }

  render() {
    return (
      <div>
        <form onSubmit={(e) => this.handleSubmit(e)}>
          <input
            type='text'
            placeholder='someone@example.com'
            value={ this.state.str}
            onChange={(e) => this.setState({ str: e.target.value })} />
          <button type='submit'>Check</button>
        </form>
        {/* <section>{ Render messages here }</section> */}
      </div>
    )
  }
}

interface IState {
  myArg: string;
  response: Array<string>;
}

Please let me know if you need any more details. Thanks in advance.

I found this article very informative:

Thanks @vipatron for sharing it with me but, my case is different as I am trying to call api every time when the state changes not only once. So, my problem is not when and where exactly call my api, I want to make the call every single time state changes

my Apologies. I was thinking that a different lifecycle hook (willUpdate) might do the trick, but what about onChange? I don’t know React super-well yet, but all my reading thus far suggests those two as candidates, although I’m not that familiar with how to handle asynchronous calls.

1 Like

Have you tried:

handleChange = (event) => {
  event.preventDefault(); // May or may not be necessary depending on what you are doing
  
  const { value } = event.target;
  const endpoint = `https://www.myapi.org/${value}`;

  fetch(endpoint)
    .then((response) => response.json())
    .then((data) => {
      // Do stuff with data and then call this.setState();
    });
}

// ...

render() {
  return(
      <div>
        <form onSubmit={(e) => this.handleSubmit(e)}>
          <input
            type='text'
            placeholder='someone@example.com'
            value={ this.state.email}
            onChange={this.handleChange} />
          <button type='submit'>Check</button>
        </form>
        {/* <section>{ Render messages here }</section> */}
      </div>
  );
}

EDIT: basically what @vipatron suggested just literally a minute before me! :smile:

1 Like

Every state change triggers a render by default, so technically you can attach your api request before your setState or within its callback, however if you want more precision in which particular state or props change that you want your api call to be triggered with, you can use the componentDidUpdate() lifecycle method where the previous state (or props) are passed in as arguments and can be used to compare with your current state to trigger your call

2 Likes

Thanks @vipatron, I appreciate your help weather it solves my issue or not :hugs:

1 Like

@honmanyau the problem with this way is, I am not able to type in textfield. it sends a request every time I press a key but, what I want to achieve is sending a request with what I type and continuously. what I mean by that:

the solution you provided:
let’s say I type
a
it doesn’t show that I typed ‘a’ while it calls api with and if I continue to type, let’s say then I type
b
again it doesn’t show typed letter in textfield and calls api with ‘b’

what I want to achieve is the following behaviour:
pressed 'a’
a
fetch('api/a');

pressed 'b’
ab

fetch('api/ab');
      .
      .
      .

and so on

and when I press submit, calls api with the current value I have in text field and then reset it

Thanks @Dereje1 componentDidUpdate(preveProps, prevState) { } is ideal for what I was trying to achieve. It fixed my issue

  componentDidUpdate(prevProps: any, prevState: any) {
      const { str } = this.state;
      if(str !== prevState.str){
          console.log('update state!');
          this.verifyIT(str);
      }

  }

Thanks for your help again and thanks @honmanyau and @vipatron

2 Likes

Insted of componentWillMount use componentWillUpdate