1

I am trying to write my first React app and it is supposed to generate QR codes for different inputs and display them on a web page.

I already have my own 'library' function that does this thing for me - I only pass the data as a parameter and it returns a promise of data URL that I use as an src for an image and it's done. Here is how it works now:

class App extends Component {

    constructor(props){
        super(props);
        this.state = {
            dataUrl: '',
        }
    }

    async componentDidMount(){
        let url = await getDataURL('<some imaginary static data>');
        this.setState({dataUrl: url});
    }

    render() {
        return(
            <div className="App">
                <div>
                    <img alt="" src={this.state.dataUrl} style={{height: 200 + 'px', width: 200 + 'px'}} />
                </div>
            </div>
        );
    }
}

But now I need to call getDataURL() multiple times for some real data, e.g. I might have multiple <div>'s with different data and I need to get and render the QR code for each of them.

If I had a function, something like this:

async loadQRCode(data){
    let url = await getDataURL(data);
    return url;
}

Is there any way how to call it for each data directly from render() function? Or is there any better approach that I am missing?

3
  • 2
    Don't call functions from render(). What you do is a) update your state (using as many async operations as you like) and b) render() the state. a) and b) happen independently, and since React re-renders whenever the state changes, all render() needs to do is render the current state; it doesn't have to worry about anything else. So if you have multiple QR codes, use an array for them in your state. Commented Jul 16, 2019 at 8:15
  • @ChrisG he has a function loadQRCode which returns an image url and this is good to use it in a render. Commented Jul 16, 2019 at 8:19
  • @TheReason Even if the function is async? I'm looking at this. It will work I guess, I'm just wondering if it's good practice. Commented Jul 16, 2019 at 8:22

4 Answers 4

2

First of all, I would like to say that componentDidMount function is a static function.

But you can have an async function like loadQRCode where you can call the function and iterate the API calls and push the result into and array and then you can render the div's with the required data.

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

Comments

2

Have you tried something like this?

// some code before
this.state.listOfImages.map((image, i) =>
  <div>
    <img
      alt=""
      src={this.loadQRCode(image.src)}
      style={{height: 200 + 'px', width: 200 + 'px'}}
    />
  </div>

)
// some code after

You might need to bind a getDataURL method in a `constructor

1 Comment

But doesn't this recalculate all the QR code dataURLs on each render?
0

It's good to call API requests in componentDidMount. Then you can call setState after that.

async componentDidMount(){
        const result = await loadQRCode(`your params`);
        this.setState({ result });
    }

1 Comment

OP knows to do that. I don't see what this answer offers in terms of the question that was asked?
0

I solved this using an array of objects in constructor:

constructor(props){
    super(props);
    this.state = {
        qrCodeData: [
            {
                data: <data>
                qrcode: ''
            },
            {
                data: <data>
                qrcode: ''
            },
            ...
        ]
    }
}

and in componentDidMount() I iterate over the array and call my getDataURL() function to set qrcode.

async componentDidMount(){
    let qrCodeDataCopy = this.state.qrCodeData.slice();
    for (let item of qrCodeDataCopy) {
        item.qrcode = await getDataURL(item.data);
    }
    this.setState({qrCodeData: qrCodeDataCopy});
}

Comments

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.