mrWiga
mrWiga

Reputation: 151

Uncaught Error: Objects are not valid as a React child (found: [object HTMLImageElement])

In reactjs how do I dynamically update the QR code component when props change. I'm using this npm package: https://www.npmjs.com/package/kjua

componentWillMount() function is working on first load but it doesn't get updated but if I render {this.state.el} then I would get: *react-dom.development.js:57 Uncaught Error: Objects are not valid as a React child (found: [object HTMLImageElement]). If you meant to render a collection of children, use an array instead.*

  ```
    import React, { Component } from 'react';
    import kjua from "kjua";
    
    class QrCodeOnAmountEntered extends Component {
      constructor(props) {
        super(props);
        this.state = {
          el: kjua({
            text: `amount=${
              this.props.text
            }&memo=xxxx`
          }),
          amount: this.props.text
        };
      }
      
      componentWillMount(){
        document.querySelector('body').appendChild(this.state.el);
      }
    
      render() {
        return (
          <React.Fragment>
            QrCodeOnAmountEntered amount: {this.props.text}
            
    <p>Print QRCode here:</p>{this.state.el}
            
          </React.Fragment>
        );
      }
    }
    
    
    export default QrCodeOnAmountEntered; ```

I need to be able to dynamically update the QRCode when props amount value changed.

Upvotes: 1

Views: 545

Answers (1)

Drew Reese
Drew Reese

Reputation: 202836

Saving props to state is a react anti-pattern (in the case of props.text => this.state.amount), and use of componentWillMount isn't recommended, but instead use componentDidMount to issue side-effects after the component mounts.

I tried looking at the docs for kjua but it seems pretty dated. I assume you pass it some 'text' and it returns an QR code image of that text. HTMLImageElement appears to not be renderable in react as an object, but perhaps ,src will allow you to render it into an <img> tag.

render() {
  const { el } = this.state;
  return (
    <React.Fragment>
      QrCodeOnAmountEntered amount: {this.props.text}
      <p>Print QRCode here:</p>
      {el && <img src={el.src}/>}
    </React.Fragment>
  );
}

Assuming calls to kjua with text data returns a new image, then you want to use componentDidUpdate to check that new props have arrived, and if so, get new QR image and save to state:

componentDidUpdate(prevState, prevProps) {
  // if current text value is not equal to the previous, calculate
  // and save new QR code image in el, else ignore
  if (prevProps.text !== this.props.text) {
    const newQRcode = kjua({ text: `amount=${this.props.text}&memo=xxxx` });
    this.setState({ el: newQRcode });
  }
}

Upvotes: 1

Related Questions