Home > front end >  How to correctly replace the layout when the handler is triggered?
How to correctly replace the layout when the handler is triggered?

Time:04-29

I have a UserCard component.

Its the component code:

class UserCard extends React.Component {
  constructor(user) {
    super(user);
  }

  render() {
    const getInitials = (str) => {
      const wordsArr = str.split(" ");
      const initialsArr = wordsArr.map((word) => word[0]);
      const initialsStr = initialsArr.join(" ");
      return initialsStr;
    };

    const {
      id,
      firstName,
      lastName,
      profilePicture,
      cardDescription = "Lorem ipsum dolor sit amet consectetur adipisicing elit. Officia rerum libero nobis laboriosam, quisquam iure placeat quae eos velit fuga?",
    } = this.props;

    const UserCard = (
      <li className="userCardWrapper">
        <article className="cardContainer" id={id}>
          <div className="cardImgWrapper">
            <img
              className="cardImg"
              src={profilePicture}
              alt={`${firstName} ${lastName} photo`}
            />
            <div className="initials">
              {getInitials(`${firstName} ${lastName}`)}
            </div>
          </div>
          <h2 className="cardName">{`${firstName} ${lastName}`}</h2>
          <p className="cardDescription">{cardDescription}</p>
        </article>
      </li>
    );

    return UserCard;
  }
}

In the component code, I have a div that follows right after the image is rendered:

<div className="initials">
   {getInitials(`${firstName} ${lastName}`)}
 </div>

I need this div as a stub in case the image doesn't load.

My task is to remake this logic. This div should only be returned if the image didn't load. If the image has loaded, the stub div is not needed. I'm trying to return it with an onError handler that I hang on img, but it doesn't work... the whole project crashes.

Question: how to hang on the onError handler the return of this div? Is it really possible to create a separate component for this small stub?

CodePudding user response:

What you could do is to use state in your component.

What you'd need to do is the following:

  1. Introduce a state in which you save the info if loading the image failed
  2. Render the image or the substitution conditionally depending on the state
  3. alter the state when one rror of the image-tag triggers

See the code below for an example implementation

class UserCard extends React.Component {
      constructor(user) {
        super(user);
      }
      
      // state component which contains the info if the image-load failed
      state = {
        loadError: false
      }
    
      render() {
        const getInitials = (str) => {
          const wordsArr = str.split(" ");
          const initialsArr = wordsArr.map((word) => word[0]);
          const initialsStr = initialsArr.join(" ");
          return initialsStr;
        };
    
        const {
          id,
          firstName,
          lastName,
          profilePicture,
          cardDescription = "Lorem ipsum dolor sit amet consectetur adipisicing elit. Officia rerum libero nobis laboriosam, quisquam iure placeat quae eos velit fuga?",
        } = this.props;
    
        const UserCard = (
          <li className="userCardWrapper">
            <article className="cardContainer" id={id}>
              <div className="cardImgWrapper">
                {
                    // render the image tag if no error occured
                    // use img.onError to set this.state.loadError to true if image load fails
                    // render substitution element if loading the image failed
                    !this.state.loadError 
                        ? <img
                              className="cardImg"
                              src={profilePicture}
                              alt={`${firstName} ${lastName} photo`
                              one rror={() => setState({loadError: true})}
                          }
                            />
                        : <div className="initials">
                           {getInitials(`${firstName} ${lastName}`)}
                         </div>
                }
                <div className="initials">
                  {getInitials(`${firstName} ${lastName}`)}
                </div>
              </div>
              <h2 className="cardName">{`${firstName} ${lastName}`}</h2>
              <p className="cardDescription">{cardDescription}</p>
            </article>
          </li>
        );
    
        return UserCard;
      }
    }
  • Related