1

I am using Clarifai API face detection and it is unable to fetch the URL which is provided from the constructor, rather than a variable which Clarifai provides in the default code

    class App extends Component{

  constructor(){
    super();
    this.state = {
      input : '',
      IMAGE_URL: '',
    }
  }
  onInputChange = (event) =>{
    this.setState({input: event.target.value});
  }

  onSubmit = () =>{
    this.setState({IMAGE_URL : this.state.input});
    const raw = JSON.stringify({
      "user_app_id": {
          "user_id": USER_ID,
          "app_id": APP_ID
      },
      "inputs": [
          {
              "data": {
                  "image": {
                      "url": this.state.IMAGE_URL
                  }
              }
          }
      ]
  });

  const requestOptions = {
      method: 'POST',
      headers: {
          'Accept': 'application/json',
          'Authorization': 'Key ' + PAT
      },
      body: raw
  };

  // NOTE: MODEL_VERSION_ID is optional, you can also call prediction with the MODEL_ID only
  // https://api.clarifai.com/v2/models/{YOUR_MODEL_ID}/outputs
  // this will default to the latest version_id

  fetch("https://api.clarifai.com/v2/models/" + MODEL_ID + "/versions/" + MODEL_VERSION_ID + "/outputs", requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
  }

I started facing this issue when I added IMAGE_URL in constructor to update it from my input form on the webpage. It works fine if i move IMAGE_URL out from the constructor and making it a variable and hard code the image url in the editor

Edit: This is the code after some tweaks. Still same error

onInputChange = (event) =>{
    this.setState({input: event.target.value});
    console.log(typeof(input),'TYPE OF INPUT');
    var inp = this.state.input;
    return inp
     //console.log(inp);
     console.log(typeof(inp)); //it is string here
  }

  onSubmit = () =>{
    this.setState({IMAGE_URL : this.state.inp});
    
    const raw = JSON.stringify({
      "user_app_id": {
          "user_id": USER_ID,
          "app_id": APP_ID
      },
      "inputs": [
          {
              "data": {
                  "image": {
                      "url": this.state.IMAGE_URL
                  }
              }
          }
      ]

Edit 2: It's working now and I guess I broke some rules. I have declared a global variable and passed the value of the input field to it and then used it in my API.

var inp = ''; //THIS IS THE NEW VARIABLE
class App extends Component{

  constructor(){
    super();
    this.state = {
      input : '',
      IMAGE_URL: '',
    }
  }
  onInputChange = (event) =>{
    this.setState({input: event.target.value}); 
    
    
    
    inp = event.target.value;
    console.log(inp);
    return inp;
   
  }

  onSubmit = () =>{
    console.log('*********',inp,'***********');
    this.setState({IMAGE_URL : this.state.input});
    
    const raw = JSON.stringify({
      "user_app_id": {
          "user_id": USER_ID,
          "app_id": APP_ID
      },
      "inputs": [
          {
              "data": {
                  "image": {
                      "url": inp
                  }
              }
          }
      ]
  • Can you do a console.log of both the `raw` variable when you're using it hard coded vs. dynamic? The only thing I am seeing is that maybe the type isn't the same (i.e. string) and its causing the `raw` string to encode as something different. – syntheticgio Aug 03 '22 at 12:56
  • @syntheticgio raw variable with dynamic input {"user_app_id":{"user_id":"kkf1d032jwpm","app_id":"my-first-application"},"inputs":[{"data":{"image":{}}}]} – Mirza Viraad Baig Aug 04 '22 at 07:06
  • raw variable with hard coded input {"user_app_id":{"user_id":"kkf1d032jwpm","app_id":"my-first-application"},"inputs":[{"data":{"image":{"url":"https://i0.wp.com/post.medicalnewstoday.com/wp-content/uploads/sites/3/2020/03/GettyImages-1092658864_hero-1024x575.jpg?w=1155&h=1528"}}}]} – Mirza Viraad Baig Aug 04 '22 at 07:07
  • @syntheticgio you were right. I console.log typeof IMAGE_URL in dynamic one and it was undefined and i managed to convert it into string by storing it in another variable. However, it seems to be just disappearing when i use it as url in API. I am completely lost – Mirza Viraad Baig Aug 04 '22 at 08:09
  • Added a comment that I think explains what is going on; sorry for the delay in the response :) – syntheticgio Aug 19 '22 at 19:49

1 Answers1

0

Seems like you've found a workaround with a global variable; but I think the actual problem was with:

this.setState({IMAGE_URL : this.state.input});

in the onSubmit function.

The setState function in react:

Think of setState() as a request rather than an immediate command to update the component. For better perceived performance, React may delay it, and then update several components in a single pass.

https://reactjs.org/docs/react-component.html#setstate

So basically you're making a request to update that variable (IMAGE_URL) and then immediately using it. Since React is trying to optimize writes, you are trying to use it before it is actually updated. You can request that update and then use the already populated version if you want.

I think the following code should work and allow you to keep out of the global scope (if that bothers you).

class App extends Component{

  constructor(){
    super();
    this.state = {
      input : '',
      IMAGE_URL: '',
    }
  }
  onInputChange = (event) =>{
    this.setState({input: event.target.value});
  }

  onSubmit = () =>{

    // This may not trigger right away, but if you want to transfer the this.state.input to this.state.IMAGE_URL it _eventually_ will
    this.setState({IMAGE_URL : this.state.input});

    const raw = JSON.stringify({
      "user_app_id": {
          "user_id": USER_ID,
          "app_id": APP_ID
      },
      "inputs": [
          {
              "data": {
                  "image": {
                      "url": this.state.input
                  }
              }
          }
      ]
  });

  const requestOptions = {
      method: 'POST',
      headers: {
          'Accept': 'application/json',
          'Authorization': 'Key ' + PAT
      },
      body: raw
  };

  // NOTE: MODEL_VERSION_ID is optional, you can also call prediction with the MODEL_ID only
  // https://api.clarifai.com/v2/models/{YOUR_MODEL_ID}/outputs
  // this will default to the latest version_id

  fetch("https://api.clarifai.com/v2/models/" + MODEL_ID + "/versions/" + MODEL_VERSION_ID + "/outputs", requestOptions)
      .then(response => response.text())
      .then(result => console.log(result))
      .catch(error => console.log('error', error));
  }
syntheticgio
  • 588
  • 6
  • 25