Search code examples
javascriptreactjsdomsemantic-ui

React dynamic component not rendering


I have this function that generates dynamic components based on an API


const renderWork = () =>{
  let DOM = []

  fetch('/api/work/')
  .then(res => res.json())
  .then(res => {
    for (let i = 0; i < res.length; i++){
      DOM.push(
        <Item id={res[i]._id}>
          <Item.Image src={res[i].imageURL} />
          <Item.Content>
            <Item.Header as='a'>Watchmen</Item.Header>
            <Item.Meta>
              <span className='cinema'>{res[i].createdDate}</span>
            </Item.Meta>
              <Item.Description>{res[i].description}</Item.Description>
            <Item.Extra>
              <Label>Hi</Label>

              <Button primary floated='right'>
                Buy tickets
                <Icon name='right chevron' />
              </Button>
            </Item.Extra>
          </Item.Content>
        </Item>
      )
    }
  })

  return DOM
}

I am trying to render those items by calling the renderWork() function in the main component

The main Componenet:

function Work(){

  return (   
    <div>
      <Nav/> 
      <div style={css.body}>
      <Item.Group divided>
        {renderWork()}
      </Item.Group>

      </div>
    </div>
  )
}

I am not sure why doesn't it render on the page I tried:

  • Making the DOM a state and change it.

  • using the useEffect hook to manage the state and/or the DOM

still, the items won't render

I am using react.semantic-UI for my components


Solution

  • I would keep api and component rendering separate.

    const renderWork = () => {
      return fetch('/api/work/')
        .then(res => res.json())
    }
    
    function WorkItem({item}) {
      return <Item id={item._id}>
              <Item.Image src={item.imageURL} />
              <Item.Content>
                <Item.Header as='a'>Watchmen</Item.Header>
                <Item.Meta>
                  <span className='cinema'>{item.createdDate}</span>
                </Item.Meta>
                  <Item.Description>{item.description}</Item.Description>
                <Item.Extra>
                  <Label>Hi</Label>
    
                  <Button primary floated='right'>
                    Buy tickets
                    <Icon name='right chevron' />
                  </Button>
                </Item.Extra>
              </Item.Content>
            </Item>
    }
    
    function Work() {
      const [items, setItems] = useState([])
    
      useEffect(() => {
        renderWork()
          .then(data => {
            setItems(data)
          })
      }, [])
    
      return (   
        <div>
          <Nav/> 
          <div style={css.body}>
          <Item.Group divided>
            {items.map(item => <WorkItem item={item}/>}
          </Item.Group>
    
          </div>
        </div>
      )
    }