Stuart Fong
Stuart Fong

Reputation: 633

React - callback in component

I am trying to make an app that gets a callback from an api, and then returns it in a function(i dont know if that makes sense). But how would I make it so that when I call that function, I attach a callback onto it, which then returns the callbacks data. It is very confusing trying to describe it so ill try to explain as I enter my code...

uploadToCloudinary(file){
    const CLOUDINARY_URL = "MY_CLOUDINARY_URL";
    const CLOUDIARY_UPLOAD_PRESET = "MY_CLOUDIARY_UPLOAD_PRESET"
    let formData = new FormData();

    formData.append("file", file);
    formData.append("upload_preset", CLOUDIARY_UPLOAD_PRESET)

    axios({
      url: CLOUDINARY_URL,
      method: "POST",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded"
      },
      data: formData
    }).then(function(res){
      callback(new Meteor.Error(400, "Error"), res);
    }).catch(function(err){
      console.log(err);
    })
    console.log(file);
  }

So here what I am doing is i am getting the file argument and entering it into cloudinary(file handling api) and trying to make a callback when it recieves the data. I understand the concept of callbacks(sorta) amd how to use them, but I am not really sure on how to make a function have a callback.

  addNote(e){
    e.preventDefault();
    let title = this.refs.title.value;
    let subject = this.refs.subject.value;
    let description = this.refs.description.value;
    let allUrls = [this.refs.imageURL.value].concat(this.state.urls);
    let imageURL = allUrls.filter(function(entry) { return entry.trim() != ''; });
    let userId = Meteor.userId();
    let userEmail = Meteor.user().emails[0].address;
    let createdAt = Date.parse(new Date());
    let unit = this.refs.unit.value;
    let file = this.refs.fileInput.files[0];

    if(!Meteor.userId()){
      this.setState({
        message: "You need to login before you can add a note",
        loginMessage: <Link to="/login">Login</Link>
      })
      throw new Meteor.Error(400, "User is not signed in.")
    }

    if(title && subject && description && unit){
      if(imageURL || file){
          let noteInfo = { title, subject, description, imageURL, userId, userEmail, createdAt, unit };
          this.uploadToCloudinary(file, (err, res) => {
            console.log(res)
          });
          //need to make a callback for this^^^^ (ln 52)
          Meteor.call("notes.insert", noteInfo, (err, res) => {
            if(err){
              this.setState({message: err.reason});
              console.log(err)
            }else{
              this.props.history.push("/")
            }
          })
        }else {
          this.setState({ message: "You must fill in all the blanks.  " })
        }
      }
  }

here is where I am attempting to call the function and hopefully get the error/response. So my question is how do I make a callback in a react component? I keep getting an error of callback is not defined.

Upvotes: 0

Views: 133

Answers (2)

Santiago Benitez
Santiago Benitez

Reputation: 362

Hey what you did is not entirely wrong though instead of delegating the responsibility of how the request is handled what you could is return the promise from the upload function and then add handlers for then and catch. Does it make sense? Then you can manage what's coming from the server yourself and update the state accordingly. If it helps I could write you a code sample let me know. Aside from that your error is because you're not passing as a parameter the callback

Upvotes: 1

Chase DeAnda
Chase DeAnda

Reputation: 16441

Your error is coming from this piece of code:

axios({
    url: CLOUDINARY_URL,
    method: "POST",
    headers: {
        "Content-Type": "application/x-www-form-urlencoded"
    },
    data: formData
}).then(function(res){

    // Right here...callback hasn't been defined anywhere
    callback(new Meteor.Error(400, "Error"), res);

}).catch(function(err){
    console.log(err);
});

Looks like you just need to update your uploadToCloudinary function params to accept the callback:

// Add a second param here
uploadToCloudinary(file, callback){
    const CLOUDINARY_URL = "MY_CLOUDINARY_URL";
    const CLOUDIARY_UPLOAD_PRESET = "MY_CLOUDIARY_UPLOAD_PRESET"
    let formData = new FormData();

    formData.append("file", file);
    formData.append("upload_preset", CLOUDIARY_UPLOAD_PRESET)

    axios({
        url: CLOUDINARY_URL,
        method: "POST",
        headers: {
            "Content-Type": "application/x-www-form-urlencoded"
        },
        data: formData
    }).then(function(res){
        callback(new Meteor.Error(400, "Error"), res);
    }).catch(function(err){
        console.log(err);
    })
    console.log(file);
}

Upvotes: 0

Related Questions