skip to Main Content

end app for woocommerce store, but i have problem rendering the first image of array in
when i console.log(images.src) i see the list of urls of the images, but in img src= it return : TypeError: Cannot read property ‘src’ of undefined
I will be very thankful to help me correctly map the images.
here is my code:

class App extends React.Component  {
  constructor(props) {
    super(props);
    this.getPosts = this.getPosts.bind(this);
    this.state = {
    posts : [],
    images: []
    };
  }
  getPosts = async () => {
    let res = await api.get("products", {
      per_page: 20,
    })

    let { data } = await res;
    this.setState({ posts: data });
  }

 componentDidMount = async () => {
  await this.getPosts();
};
 render() {
  const { posts } = this.state;
  const { images } = this.state
  return(
    <div>
   <Head>
      <title>Онлайн магазин KIKI.BG</title>
      <link rel="icon" href="/favicon.ico" />

 </Head>

 <React.Fragment >
                {posts.map((posts, index ) => {
                  { 
                    posts.images.map((images, subindex) =>

                  console.log(images.src),
                    <img src={images[0].src} />
                    )}
                    return (
                      <div>
                <h1>{posts.name}</h1>
                <h2>{posts.price}</h2>
                             </div>  
                             )})}
          </React.Fragment>

 </div>
  )
}
  }
  export default App;

3

Answers


  1.             {posts.map((posts, index ) => {
                  { 
                    posts.images.src.map((image, subindex) =>
    
                    <img src={image.src} />
                    )}
                    return (
                      <div>
                           <h1>{posts.name}</h1>
                           <h2>{posts.price}</h2>
                     </div>  
                    )
                  })}
    
    Login or Signup to reply.
  2. well, console.log(images.src) i see the list of urls of the images doesn’t make any sense.. images is array. So images[0] should be image with data with property src on it?. Btw a lot of stuff in this code is just wrong.

    • Don’t rebind getPosts already bound getPosts function in constructor (via class property) (getPosts). BTW you dont need to bind is here at all, its not called as a callback.
    • Its weird, that you call await res after api.get() … shouldn’t be it just await api.get()? Another await is usually used on fetch, when you do something like await response.json().
    • There is no need for async/await in componentDidMount
    • If getPosts will throw it will mess up your component, its better to handle error in catch and call props.onError(error) for example
    • You don’t have any key attributes on element in map, thats wrong. You should put some unique id there (url fe? if not same, or id) for proper component re-render.
    • You have some weird brackets issue in your maps…
    • You shouldn’t use more than one h1 one the page 🙂
    • images.src should be string, not array…
    • Why is there subindex and index when u are not using it?
    • Why you store images when they are not filled anywhere? Are they in the response of get? Thats maybe why u get an TypeError !
    • I would add loading and no data message…

    That would be my code:

    import { Component, Fragment } from 'react';
    
    class App extends Component {
    
      static defaultProps = {
        onError: console.error;
      };
    
      state = {
        posts: [],
        images: [],
        loading: false,
      };
    
      // This could be done with hooks much better tho...
      async componentDidMount () {
         this.setState({ loading: true });
    
         try {      
           await this._fetchData();
         }
         catch (error) {
           this.props.onError(error); // Or something rendered in state.error?
         }
         finally {
           this.setState({ loading: false });
         }
      }
    
      render () {
        const { images, posts, loading } = this.state;
    
        if (!images.length) {
          return <div>No data.</div>;
        }
    
        if (loading) {
          return <div>Loading</div>;
        }
    
        const postBoxes = posts.map((post, index) => {
          const image = images[index];
          // Because you don't know, if that specific image is there... if this are your data..
          const imageElement = image ? 
             <img src={image.src} alt="dont know" /> :
             null;
          const { name, price } = post;
    
          // If name is unique, otherwise some id.
          return (
            <Fragment key={name} >
              {imageElement}
    
              <h2>{name}</h2>
              <h3>{price}</h3>            
            </Fragment>
          );      
        });
    
        return (
          <div>
            <Head>
              <title>Онлайн магазин KIKI.BG</title>
              <link rel="icon" href="/favicon.ico" />
            </Head>
    
            <Fragment>
              {postBoxes}
            </Fragment>
          </div>
        );
      }
    
      async _fetchData () {
        const { data } = await api.get('products', { per_page: 20 });
    
        const { posts, images } = data;
    
        this.setState({ posts, images });
      }
    }
    
    
    export default App;
    
    Login or Signup to reply.
  3. if console.log(images.src) -> gives list of images.

    Then,

    <img src={images.src[0]}/> -> should do the trick.

    may be, Add a null check to be certain.

      images.src[0] && <img src={images.src[0]}/>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search