I am learning React.js for college and am a bit stuck. I am getting this error:
weathers.map not a function
I am sure it's something simple but can't figure it out! It is a standard create-react-app, created a directory called components and these 2 files live there:
Weathers.js:
import {useState} from 'react'
import axios from 'axios'
import Weather from './Weather'
function Weathers() {
const [weathers, setWeathers] = useState()
const [city, setCity] = useState('')
const API = {
link: "http://api.openweathermap.org/data/2.5/weather?q=",
key: "&appid=xxxxx"
}
function handleSearchCity(e) {
e.preventDefault()
setCity(e.target.value)
}
async function searchWeathers(e) {
e.preventDefault()
console.log()
var response = await axios.get(API.link + city + API.key)
console.log(response)
setWeathers(response.data)
}
return (
<div>
<input value={city} onChange={handleSearchCity} />
<button onClick={searchWeathers}>Search</button>
<div>
</div>
{
weathers.map(function(i, index){
return (
<div>
<Weather name={i.name} />
</div>
)
})
}
</div>
)
}
export default Weathers;
Weather.js:
function Weather(props) {
return (
<div>
{props.name}
</div>
);
}
export default Weather;
You are getting an error because the result from the api is not an array. It is an object that looks like this (for London):
{
"coord": {
"lon": -0.1257,
"lat": 51.5085
},
"weather": [
{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10n"
}
],
"base": "stations",
"main": {
"temp": 278.91,
"feels_like": 276.51,
"temp_min": 277.25,
"temp_max": 280.02,
"pressure": 1021,
"humidity": 88
},
"visibility": 10000,
"wind": {
"speed": 3.09,
"deg": 330
},
"rain": {
"1h": 0.89
},
"clouds": {
"all": 100
},
"dt": 1646438029,
"sys": {
"type": 2,
"id": 2019646,
"country": "GB",
"sunrise": 1646375984,
"sunset": 1646415906
},
"timezone": 0,
"id": 2643743,
"name": "London",
"cod": 200
}
If you want the name propriety inside the result, you could get it like so:
import {useState} from 'react'
import axios from 'axios'
import Weather from './Weather'
function Weathers() {
const [weathers, setWeathers] = useState()
const [city, setCity] = useState('')
const API = {
link: "http://api.openweathermap.org/data/2.5/weather?q=",
key: "&appid=xxxxx"
}
function handleSearchCity(e) {
e.preventDefault()
setCity(e.target.value)
}
async function searchWeathers(e) {
e.preventDefault()
console.log()
var response = await axios.get(API.link + city + API.key)
console.log(response)
setWeathers(response.data)
}
return (
<div>
<input value={city} onChange={handleSearchCity} />
<button onClick={searchWeathers}>Search</button>
{weathers && <Weather name={weathers.name} />}
</div>
)
}
export default Weathers;
Since weathers is initialized to an empty array, you shouldn't actually have the error weathers.map is not a function.
Maybe you can add a conditional rendering to only return the jsx expression when you get the weathers data from the API.
return weathers && (
<div>
// ...
</div>
)
}
export default Weathers;
Related
I am using use-axios hooks in my React application to fetch data from an API and paginate it with 5 items each page.
Sandbox: https://codesandbox.io/s/axios-hooks-infinite-scrolling-forked-hxbnq?file=/src/index.js
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import useAxios from "axios-hooks";
function App() {
const [dataPerPage, setDataPerPage] = useState({});
const [page, setPage] = useState(1);
const [{ data, loading, error }] = useAxios({
url: "http://localhost:6366/api/rule-sets",
params: { page: page }
});
useEffect(() => {
setDataPerPage((d) => ({ ...d, [page]: data }));
}, [page, data]);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error!</p>;
return (
<div>
<button onClick={() => setPage((p) => p + 1)}>load more</button>
<pre>
{JSON.stringify(
[].concat(...Object.values(dataPerPage).map((p: any) => p)),
null,
2
)}
</pre>
</div>
);
}
The API is returning me this:
[
{
"user": {
"username": "q123123",
"displayName": "John Snow"
},
"active": false,
"_id": "612496f44683924ea85d731b",
"filename": "my file 2.xls",
"rules": [
{
"_id": "612496f44683924ea85d731c",
"sourceSystem": "CRM_MOBILE",
"classifications": "OPT,BLM",
"segment": null,
"calendar": "Standard",
"createSla": true,
"slaDurationInMinutes": 300,
"sendNotification": true,
"useHolidays": false
}
],
"createdAt": "2021-08-24T06:51:32.552Z",
"updatedAt": "2021-08-24T06:51:32.552Z",
"__v": 0
},
...
]
I want now to pass each object in the Array to my <RuleSetsItem> component as a prop:
<RuleSetsItem ruleSets={ruleSet} />
But I can not iterate it like this:
{ [].concat(...Object.values(dataPerPage).map((p: any) => (
p ? p.map(item => <RuleSetsItem>) : ''
)))}
as there is no map possible and also the first render is undefinded || null.
I also tried it with Object.keys(p).map() but this just returns me 01234.
This is my original implementation as reference before I implemented pagination with just a basic GET that returned me all stored items:
{ruleSets?.length
? ruleSets.map((ruleSet: RuleSetType) => (
<div key={ruleSet._id}>
<RuleSetsItem ruleSets={ruleSet} />
</div>
))
: ''}
Hello stackoverflow members. So I wanna call this action nested array in json to Action Component but I dont know how. If I could get some help that would be highly appriciated
import React from 'react'
import data from "../data.json";
function Action() {
return (
<div>
{data.map((postData) => {
console.log(postData);
return(
<div key={postData.id}>
<h1 >{postData.action.name}</h1>
</div>
)})}
</div>
)
}
export default Action
[
{
"action":[{
"id":"0",
"image": "src=fsdf",
"price" : "60$",
"name" :"cs"
},
{
"id":"1",
"image": "src=fsdf",
"price" : "6$",
"name" :"whatever"
}],
"adventure":[{
"id":"10",
"image": "src=fsdf",
"price" : "60$",
"name" :"Cs"
}]
}
]
You need to store your data.json file in the public folder if you want to access the data in json format and then make use of useEffect Hook and fetching data within useEffect() Hook itself to get the data.
Here is the WORKING DEMO on Codesandbox:
https://codesandbox.io/s/json-fanda-stydg
FULL CODE:
import React from "react";
import { useEffect, useState } from "react";
import "./styles.css";
function App() {
const [data, setData] = useState([]);
useEffect(() => {
fetch("./data/data.json")
.then((response) => response.json())
.then((json) => {
console.log(json);
setData(json);
});
});
return (
<div>
{data.length > 0 &&
data.map((postData) => {
console.log(postData);
return (
<div key={data.id}>
{postData.action.map((action) => {
return <h1>{action.name}</h1>;
})}
<p>
{postData.adventure.map((adventure) => {
return <h1>{adventure.name}</h1>;
})}
</p>
</div>
);
})}
</div>
);
}
export default App;
JSON: You JSON is perfectly fine :)
[
{
"action": [
{
"id": "0",
"image": "src=fsdf",
"price": "60$",
"name": "cs"
},
{
"id": "1",
"image": "src=fsdf",
"price": "6$",
"name": "whatever"
}
],
"adventure": [
{
"id": "10",
"image": "src=fsdf",
"price": "60$",
"name": "Cs"
}
]
}
]
You could change your code to something like this:
import data from "../data.json";
//...
export default function App() {
return (
<div className="App">
<div>
{data[0].action.map((postData) => {
return (
<div key={postData.id}>
<h1>{postData.name}</h1>
</div>
);
})}
</div>
</div>
);
}
data is an array with one object with two properties: action and adventure that are arrays.
As prasanth points out given your current data you could also remove the outer most array and make data a single object.
Then you can just map over data.action.
sandbox
So I have a problem with passing data from one Component to another. So I have Free To Play Component which has is taking freetoplay array from json and displaying it. I have also a Link which should open up a Payment Route and pass the data, In the Payment I have a filter function, which is fitering objects based on their id, Anyway when I press on the Link, it should display the image class and price, but it does not, I dont know why. If anyone could help me I would be very grateful. Cheers
import React from 'react'
import { useParams, Link } from "react-router-dom";
import data from "../data.json";
function Payment() {
const { productId } = useParams();
const filteredData = data.filter((product) => product.id === productId)[0];
return (
<div className='Payment'>
<img src={filteredData.image}></img>
<h1>{filteredData.price}</h1>
<h1>{filteredData.name}</h1>
</div>
)
}
export default Payment
import React from 'react'
import data from "./data.json";
import {
Link
} from "react-router-dom";
import { SearchContext } from './SearchContext';
function FreeToPlay() {
const {filterProduct}=React.useContext(SearchContext);
return (
<>
<div className='All' >
{data[0].freetoplay.filter(filterProduct).map((product) => {
return (
<div className='f2p' key={product.id}>
<img src={product.image}></img>
<h2>{product.name}</h2>
<h5>{product.price}</h5>
<Link
to={`/payment/${product.id}`}
className='link'
>
Buy Now
</Link>
</div>
);
})}
</div>
</>
);
}
export default FreeToPlay
json
[
{
"freetoplay": [{
"id": "0",
"image": "src=fsdf",
"price": "60$",
"name": "CS Go"
},
{
"id": "1",
"image": "src=fsdf",
"price": "6$",
"name": "Fifa"
}
],
"action": [{
"id": "2",
"image": "src=fsdf",
"price": "60$",
"name": "doom"
},
{
"id": "3",
"image": "src=fsdf",
"price": "66$",
"name": "cyberpunk"
}
],
}
]
this is the Route
<Route path="/payment/:productId">
<Payment/>
</Route>
It looks like your issue might be in the handling of your data.filter in the Payment component.
You use:
const filteredData = data.filter((product) => product.id === productId)[0];
But your data imported from data.json is an object, not an array.
You must have meant either:
const filteredData = data.action.filter((product) => product.id === productId)[0];
Or:
const filteredData = data.freetoplay.filter((product) => product.id === productId)[0];
I have create VenueList component. I want to display list using FlatList component in react native app. I am getting error: Invariant Violation tried to get frame out of range index (See screenshot).
Code:
VenueList.js:
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { View, Text, FlatList, StyleSheet } from 'react-native';
import { connect } from 'react-redux';
import { fetchVenues } from '../actions/venueAction';
class VenueList extends Component {
componentWillMount () {
this.props.fetchVenues();
}
renderItem = ({ item }) => (
<View style={styles.item}>
<Text>{item.attributes.name}</Text>
</View>
);
render() {
return (
<FlatList
styles={styles.container}
data={this.props.venues}
renderItem={this.renderItem}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
item: {
padding: 16,
borderBottomWidth: 1,
borderBottomColor: '#ccc'
}
});
VenueList.propTypes = {
fetchVenues: PropTypes.func.isRequired,
venues: PropTypes.array.isRequired
}
const mapStateToProps = state => ({
venues: state.venues.items
})
export default connect (mapStateToProps, { fetchVenues })(VenueList);
venueReducer.js:
import { FETCH_VENUES } from '../actions/types';
const initialState = {
items: []
}
export default function (state = initialState, action) {
switch (action.type) {
case FETCH_VENUES:
return {
...state,
items: action.payload
};
default:
return state;
}
}
venueAction.js:
import { FETCH_VENUES } from './types';
import axios from 'axios';
export const fetchVenues = () => dispatch => {
axios.get(`my_api_link`)
.then( venues =>
dispatch({
type: FETCH_VENUES,
payload: venues
})
)
.catch( error => {
console.log(error);
});
};
The data which I want to display from API endpoint has json data as follows:
{
"data": [
{
"type": "venues",
"id": "nb",
"attributes": {
"name": "Barasti Beach",
"description": "Barasti Beach is lotacated in the awesome barasti beach",
"price_range": "$$$",
"opening_hours": "10:30-12:40/16:00-2:00",
"organization": {
"id": "GD",
"legal_name": "Barasti",
"brand": "Barasti"
},
"place": {
"address": "Le Meridien Mina Seyahi Beach Resort & Marina, Dubai Marina - Dubai - United Arab Emirates",
"latitude": "25.092648",
"location": [
"Marina Bay",
"Dubai",
"Arab Emirate United"
]
}
}
}
],
"meta": {
"total": 1,
"cursor": {
"current": 1,
"prev": null,
"next": null,
"count": 25
}
}
}
See screenshot:
As per the the above response for the api request,
The problem is with the payload which is set in the actions. You need to pass the data from the api to the Flatlist since it accepts only arrays.
axios.get(`my_api_link`)
.then( venues =>
dispatch({
type: FETCH_VENUES,
payload: venues.data
})
)
EDIT:
Adding in VenueList.js component (if the api is returning values inside data key):
renderItem = ({ item }) => (
<View style={styles.item}>
<Text>{item.attributes.name}</Text>
</View>
);
render() {
return (
<FlatList
styles={styles.container}
data={this.props.venues.data}
renderItem={this.renderItem}
/>
);
}
import React, { Component } from 'react';
import axios from 'axios';
class Meetups extends Component {
constructor(props) {
super(props);
console.log('in constructor');
this.state = {
results: [],
};
}
componentDidMount() {
console.log('meetup feed');
axios.get('https://api.meetup.com/2/categories?offset=0&format=json&photo-host=public&page=20&order=shortname&desc=false&sig_id=211627025&sig=ae69aec13f23c7837cd55c5a68b99e00719fa225')
//response
.then(response => response.json())
.then(data => this.setState({results:data.results}));
}
render() {
const {results} =this.state;
return(
<div>
{results.map(result =>
<div key={result.id} className='container'>
{result.name}
</div>
)}
</div>
);
}
}
export default Meetups;
JSON format which I'm receiving:
{
"results": [
{
"name": "Arts & Culture",
"sort_name": "Arts & Culture",
"id": 1,
"shortname": "Arts"
},
{
"name": "Book Clubs",
"sort_name": "Book Clubs",
"id": 18,
"shortname": "Book Clubs"
},
{
"name": "Career & Business",
"sort_name": "Career & Business",
"id": 2,
"shortname": "Business"
}
]
}
I am trying to use Meetup API in my project. But could not able to connect with it. There might be a problem with mapping. I want to know exact mapping for the given json format. Please help me out. Thanks
import React, { Component } from 'react';
import axios from 'axios';
class Meetups extends Component {
state = {
results: []
}
componentDidMount() {
axios.get('https://api.meetup.com/2/categories?offset=0&format=json&photo-host=public&page=20&order=shortname&desc=false&sig_id=211627025&sig=ae69aec13f23c7837cd55c5a68b99e00719fa225')
.then(response => {
let results = response.data.results;
this.setState({ results: results });
console.log(response);
})
}
render() {
let studentsDisplay = (
this.state.results.map( (result, index) =>
<div key={index} className="card" style= { {width: '18rem'} }>
{result.name}
<br/>
{result.shortname}
</div>
));
return (
<div className='container'>
{
studentsDisplay
}
</div>
);
}
}
export default Meetups;