Mirza Viraad Baig
Mirza Viraad Baig

Reputation: 59

Clarifai API not detecting the image URL in React.js

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
                  }
              }
          }
      ]

Upvotes: 1

Views: 384

Answers (1)

syntheticgio
syntheticgio

Reputation: 608

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

Upvotes: 0

Related Questions