Update React UI after updating user.profile field with Cloudinary


#1

How to update React UI elements after updating profile picture?

Trying to:

  • update avatar in Navbar
  • display uploaded picture in the same component, from which making upload

Currently have tried adding withApollo() and use client.refetchObservableQueries() and client.resetStore() neither of these work, have to manually refresh the page - any suggestions?

Here is my current function:
*using React-Dropzone to handle receiving

handleDrop = file => {

    const fd = new FormData();
    fd.append("file", file[0]);
    fd.append("upload_preset", "77777");
    fd.append("timestamp", (Date.now() / 1000) | 0);

    // Make an AJAX upload request using Axios
    const url = "https://api.cloudinary.com/v1_1/77777777/upload";
    const config = {
      headers: { "X-Requested-With": "XMLHttpRequest" }
    };

    return axios.post(url, fd, config).then(response => {
      const data = response.data;
      const fileURL = data.secure_url;

      Meteor.users.update(Meteor.userId(), {
        $set: {
          "profile.picture": fileURL
        }
      });
    });

#2

You can simply use the React component’s internal state to store the fileUrl you receive from Cloudinary, by adding a call to setState() around the same time you call Meteor.users.update(). Your display component would then read either from the user’s profile or its own state to display the picture.

If you want to leverage Meteor’s reactivity to achieve this, well, I never used Apollo, but with regular Meteor, this could be achieved by using the withTracker() HOC, tracking the user profile and passing down the url as props to your uploading/displaying component.


#3

You may use getDeriviedStateFromProps lifecycle of react. Dunno if it’s a good solution.
Use the image src as state.

  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.src !== prevState.src) {
      return {
        src: nextProps.src
      };
    }
    return null;
  }
  }
return null
}

Obviously, pass Image src to the React component from Meteor.src or Apollo query.
Hope it helps.


#4

Thanks for your reply, the state of avatar component (and thus, the fileURL), however, is in a different component, way up in the tree, if this makes sense … (?)

Hence the confusion…


#5

Makes perfect sense, yes. The simplest solution, although quite cumbersome, would be to pass a function that set the state of your display component as a prop all the way down to the uploading component, and call that instead of setState() when receiving the fileUrl.

At this point, it might be cleaner to use Meteor’s reactivity as I described in my second solution, but I have no idea how to implement that with apollo…


#6

Ok, thanks I will look into your suggested solution #2! :slight_smile:

In the mean time, I’m not closing or marking this solved, in case anyone else has any suggestions…

Thanks @pdecrat!