1

So, I have a React newbie problem with changing variables in React. How to pass this URL to the end of the component?

const logo = () => {
var logoUrl;
var userId = fire.auth().currentUser.uid;

fire.database().ref('/clients/' + userId).once('value')
.then(function(snapshot) {

var companyID = (snapshot.val().companyID) || 'Anonymous';

fire.database().ref('/company/' + companyID).once('value').then(function(snapshot) {
  logoUrl = (snapshot.val().logo) || 'No Logo';
});

});

console.log(logoUrl);
return <img src={logoUrl} />
}
5
  • 1
    What do you mean by how to pass it? Is there any value that firebase is returning to you? Also, I would suggest that you use let as opposed to var. Commented Jun 26, 2018 at 10:01
  • @brandNew yes, it returns the logo url. Commented Jun 26, 2018 at 10:02
  • Okay great. So what is the issue that you are having? Is there an error you are getting or the image jus wont display or do you want to mutate this value? Commented Jun 26, 2018 at 10:05
  • @brandNew so basically the console.log just before return shows 'undefined'. The logoUrl remains empty apparently. Commented Jun 26, 2018 at 10:08
  • Oh I see. Oh well, Javascript has a non-blocking architecture, that means, other code may run before the code above it returns the value(s) you are interested in. A way to deal with this is using promises, like you are doing maintain the returns in state for later use. Commented Jun 26, 2018 at 10:19

1 Answer 1

1

So you're doing an async API request to Firebase.

In order to use logoUrl in your component methods, first you have to keep it in the state, once its value is returned from Firabase.

Your flow should be:

  1. Trigger the API request for getting the logo.
  2. When the response is returned, then you should keep it in your component state.
  3. When it's in the state, you can access it in your component.

Keep in mind that the initial value of logoUrl is null (or whatever value you set in the constructor), while the logo is being fetched from the API. When it's null, you can show a loading message.

Something like that:

class App extends React.Component {
  constructor(props) {
    super(props)

    this.state = {
      logoUrl: null
    }
  }

  getLogo() {
    const userId = fire.auth().currentUser.uid

    fire.database().ref('/clients/' + userId).once('value')
      .then(function(snapshot) {

        let companyID = (snapshot.val().companyID) || 'Anonymous'

        fire.database().ref('/company/' + companyID)
          .once('value')
          .then(function(snapshot) {
            const logoUrl = snapshot.val().logo
            this.setState({
              logoUrl
            })
          })

      })
  }

  componentDidMount() {
    this.getLogo()
  }

  render() {
    return this.state.logoUrl ? <img src={this.state.logoUrl} /> : <div>Loading ...</div>
  }

}
Sign up to request clarification or add additional context in comments.

4 Comments

That works great. I was just trying to avoid using the stateful component for such a trivial thing like getting logo. Also - in the render method the content shown should be swapped :)
There two types of components (by a role) - containers and presentational. In your container components, like from the example, is where you should handle your API requests.
Otherwise, I don't see a proper way for handling async calls with stateless components. How the stateless component will be rerendered when the API async responce is returned? No propery way! If you want to reduce your app's boilerplate for similar trivial things (as you said), you can create a HOC that will fetch whatever you want and there you will reduce your fetching boilerplate.
Would also recommend reading the official documentation on the async rendering topic: reactjs.org/blog/2018/03/27/update-on-async-rendering.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.