0

I'm using React hooks and Typescript.

Basically, I'm grabbing data from an API through a service in useEffect, setting state through a .then(). When I log the data from this point, I can see it in the console, but the component is not updating. I'm an experienced dev but new to React completely.

Also, if I do something dumb like put {newsItems} in the return unwrapped once the data is loaded is will show an error. I'm guessing it is some simple mistake I am just blind to.

Here is the code:

import React, { Fragment, useContext, useEffect, useState } from 'react'
import { IFeedItem, IOwlerResponse, OwlerResponse } from '../../../../app/ models/owler'
import FeedItem from './FeedItem';



function formatOwlerResponse(response: any): OwlerResponse { 
    // console.log(response.feeds);
    return { feeds: response.feeds, pagination_id: response.pagination_Id }

}



class ItemService { 

    getItems(url: string): Promise<OwlerResponse> {
        return fetch(
            `https://api.owler.com/v1/feed/url?domain=${url}&format=json&limit=100`,
            {
              method: "GET",
              headers: new Headers({
                   (Redacted)

              })
            })
            .then(res => res.json())
           // .then(res => res.map((response: any) => formatOwlerResponse(response))
            .then(res => formatOwlerResponse(res))
          
            }} 




export const CompanyNewsFeed = () => {
    
    const [url, setUrl] = useState('google.com');
    const [newsItems , setNewsItems] = useState<IFeedItem[]>([])
    const [isLoading, setIsLoading] = useState(true); 
    const client = new ItemService()

    
    
    
    useEffect(()=>{
        client.getItems('google.com').then(r=> {
            console.log(r.feeds)
            setNewsItems(r.feeds); 
        })
        console.log('set')


    }, [url, formatOwlerResponse]);



    return (
        <Fragment>
                        
                 {newsItems.map(item =>{
                     <Fragment key={item.id}>
                        <h1>{item.title}</h1>
                        <p>{item.description}</p>

                     </Fragment>


                 })} 

        </Fragment>
            


        
       

    )
}

export default CompanyNewsFeed 

Update -> I made a button for forceUpdate() and refresh() when I hit those I got an error that said I might have more than one version of react installed, which would account for the odd behaviour, since I've seen tutorials mostly mapped out exactly like my application. I did have a moment where I was changing the dependences to take care of warnings and I was at various points on 16.8, 16.14, and 17.0.1 or 17.1. I had had Mobx in too, and I spent a day checking that that was setup correctly. Will update if that doesn't solve it.

Brian
  • 181
  • 1
  • 8
  • 2
    not adding a key in your map may be a cause for react update prevention – amirhe Jan 10 '21 at 08:57
  • like right under map(? – Brian Jan 10 '21 at 09:05
  • 1
    More info about map and key: https://stackoverflow.com/questions/64268908/update-state-hooks-inside-map and https://stackoverflow.com/questions/60710716/how-to-use-map-function-for-hooks-usestate-properties-dynamically and https://stackoverflow.com/questions/63064061/reactjs-hooks-update-value-of-map – react_or_angluar Jan 10 '21 at 09:08
  • what's the error that you're getting? – Taghi Khavari Jan 10 '21 at 09:11
  • I'm not getting an error, its just not updating. In the title, I'm saying if I force an error once it loads, the error shows, so its refreshing but the html is not updating (?). Thanks @jqueryHtmlCSS, I'll check those out. – Brian Jan 10 '21 at 09:13

2 Answers2

1

Just need to consider these

first you're adding [url, formatOwlerResponse] as useEffect dependency array so if none of the variables don't change so your api will only be called once.

another thing that you need to consider is that to check for newsItems length because your mapping through it and if it's not an array it would give you an error

return (
      <Fragment>
          { newsItems?.map(item =>{
              <Fragment key={item.id}>
                <h1>{item.title}</h1>
                <p>{item.description}</p>
              </Fragment>
          })} 
      </Fragment>
  )
Taghi Khavari
  • 6,272
  • 3
  • 15
  • 32
  • 1
    thanks because of typescript #2 is less of a concern since we are enforcing types, i did check and make sure, and it is always an array, either 0 or 100 in length. #1 i think is the problem. Those dependencies were a holdover, but I think basically useEffect update is causing this issue, I need to rework my use of useEffect. Idk if that will solve the problem but it might. – Brian Jan 10 '21 at 09:33
0

So the mistake here was actually none of the above. Showed this to a friend of mine in an interactive sandbox, within 10 minutes he saw that this:

             {newsItems.map(item =>{
                 <Fragment key={item.id}>
                    <h1>{item.title}</h1>
                    <p>{item.description}</p>

                 </Fragment>


             })} 

Should be

             {newsItems.map(item =>(
                 <Fragment key={item.id}>
                    <h1>{item.title}</h1>
                    <p>{item.description}</p>

                 </Fragment>


             ))} 

Can't believe I didn't see it.

Brian
  • 181
  • 1
  • 8