2

I've followed some fairly basic tutorials to set up a basic Web Api service and a React TS app to consume this, but when my react component calls the WebApi service, I can see the Web Api gets stepped into and returns the data - as it does if I enter the API url in the browser, it returns the correct items JSON, but in the javascript code for React, the HTTP response doesn't appear to contain any data when the promise comes back from fetch, just an empty 200 response.

Ie response.data is undefined.

This must be something very basic I'm doing wrong - as like I mentioned when you enter the API url in the browser, you see the correct JSON in the browser. So why cant my react code understand the response?

My Web Api

 [EnableCors("*", "*", "*")]
    public class ItemsController : ApiController
    {
        private readonly Item[] _items = {
            new Item
            {
                ...
            },
            new Item
            {
                ...
            },
            new Item
            {
                ...
            },
        };

        public HttpResponseMessage Get()
        {
            return Request.CreateResponse(HttpStatusCode.OK, _items);
        }

        public HttpResponseMessage Get(long id)
        {
            var item= _items.FirstOrDefault(t => t.ItemId == id);
            if (item== null)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Not found");
            }

            return Request.CreateResponse(HttpStatusCode.OK, item);
        }
    }

My react component

import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import '../../App.css';
import IStoreState from '../../interfaces/IStoreState';
import Item from '../../model/item';
import { getItemsReceivedAction } from './actions';

interface IItemsProps {
    items: Item[],
    itemsUpdated: (items:Item[]) => void
}

class Trades extends React.Component<IItemsProps> {
    constructor(props:IItemsProps) {
        super(props);
    }

  public componentDidMount() {
        fetch('http://localhost:58675/api/items', {
            headers: {
                Accept: 'application/json',
            },
            method: 'GET'            
        }).then((t:any) => 
            {
                const results = t;
                this.props.itemsUpdated(results.data);
            }                        );
    }

    public render() {
        return (
            <div>                
                {this.props.items} items displayed
            </div>
        );
    }

}

const mapDispatchToProps = (dispatch:Dispatch) => {
    return {
        itemsUpdated: (items:Item[]) => dispatch(getItemsReceivedAction(items))
    }
}

function mapStateToProps(state:IStoreState) {
    return {
        items: state.viewingItems
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(Items);

Edit: javascript results object below

body: (...)
bodyUsed: false
headers: Headers {}
ok: true
redirected: false
status: 200
statusText: "OK"
type: "cors"
url: "http://localhost:58675/api/items"
__proto__: Response
2
  • 2
    are you sure the items are in results.data and not results ? I think this is your problem. Try changing this.props.itemsUpdated(results.data); to this.props.itemsUpdated(results); Commented Jan 7, 2019 at 12:16
  • results appears to be a Response object, body updated in the main question above Commented Jan 7, 2019 at 12:20

1 Answer 1

1

It sees to me that the problem is in the fetch part of you react component. What you get in the first then callback is a Response object.

In order to get the data from it, you need to call one of it's methods (which return a promise). In your case, since the response contains json, you need to call the json() method. After that, you chain another then where you manipulate the parsed data:

fetch('http://localhost:58675/api/items', {
        headers: {
            Accept: 'application/json',
        },
        method: 'GET'            
    }).then((t:any) => 
        {
            return t.json(); // <-- this part is missing
        }
    ).then((t:any) => 
        {
            const results = t;
            this.props.itemsUpdated(results.data);
        }
    )
Sign up to request clarification or add additional context in comments.

2 Comments

Perfect, knew it was something simple. Is that because im receiving the response correctly but it doesnt automatically try and serialise it via JSON - so I have to call the json() extension method to do so?
Yep, I've updated the answer with more details. Basically, the Response object has a bunch of methods, like json, blob, formData and so on and you have to use the right one, depending on what data you expect. I've tripped on that myself quite a lot ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.