基于React Redux的Foursquare API搜索应用:无法读取JSON字段报错
Hey there! Let's break down why you're seeing those frustrating "Not found" errors even though the full JSON data shows up in your console. This is super common with nested API responses and async state handling—here's how to fix it:
1. You're Not Accessing the Correct Nested Fields
Foursquare's API returns deeply nested data, so chances are you're targeting the wrong path for address, photos, or tips. Let's clarify:
- Address: Lives inside the
locationobject of each venue, not directly on the venue itself. So usevenue?.location?.addressinstead ofvenue.address. - Photos: The search endpoint only returns a photo count and basic structure. To get actual photo URLs, you need to access the
itemsarray insidephotos, then construct the URL usingprefix + "300x300" + suffix(adjust dimensions as needed). - Tips: Important note—tips aren't included in the
venues/searchresponse! You'll need to make a separate API call tohttps://api.foursquare.com/v2/venues/{venueId}/tipsto fetch tips for each venue.
Example Safe Access:
// Address with fallback text {venue?.location?.address || "No address available"} // Photo URL with fallback {venue?.photos?.items?.length > 0 ? `${venue.photos.items[0].prefix}300x300${venue.photos.items[0].suffix}` : "No photo available"}
2. Async State Loading Race Condition
Since your fetchVenues action is asynchronous, your component might render before the Redux state is updated with the venue data. When you try to access fields on undefined or an empty array, you get "Not found" errors.
Fixes:
- Add a loading state in your Redux reducer to show a spinner or placeholder while data loads.
- Use conditional rendering to only render venue data once it exists:
{loading ? ( <p>Loading venues...</p> ) : ( venues.map(venue => ( <div key={venue.id}> {/* Safe field access here */} </div> )) )}
3. Ensure Redux is Storing the Correct Data
Double-check your action creator to make sure you're extracting the venues from the API response correctly. Foursquare wraps venues in response.venues, so your action should look like this:
export const fetchVenues = (place, location) => dispatch => { fetch(`https://api.foursquare.com/v2/venues/search?near=${location}&query=${place}&limit=10&client_id=${api_id}&client_secret=${api_key}&v=20180323`) .then(res => res.json()) .then(data => { // Make sure you're targeting data.response.venues dispatch({ type: 'FETCH_VENUES_SUCCESS', payload: data.response.venues }); }) .catch(err => dispatch({ type: 'FETCH_VENUES_ERROR', payload: err })); };
4. Handle Optional Fields Gracefully
Not all venues will have an address, photos, or (as we noted) tips. Always add fallback text to avoid empty spaces or errors when these fields are missing.
内容的提问来源于stack exchange,提问作者MontyGoldy

