I currently have this React component that is going to list bottles of alcohol. I'm running into an issue where, although my components state gets returned, I am still not able to map over it.
import React, { Component } from "react";
import Table from 'react-bootstrap/Table'
import Layout from '../../components/layout'
import axios from 'axios';
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
export default class Bottles extends Component {
constructor(props) {
super(props)
this.state = { bottles: [] }
}
componentDidMount() {
axios.get(`http://localhost:3000/api/v1/bottles`)
.then(res => {
const bottles = res.data;
this.setState({ bottles });
})
.catch(function (error) {
console.log(error);
})
}
render() {
return (
<Layout css={{ padding: 0 }} pageTitle="Bottles">
<ul>
{ console.log(this.state.bottles) }
{ this.state.bottles.map(bottle => <li>{bottle.id}</li>)}
</ul>
</Layout>
)
}
}
I have a console log in the render and it seems to render two different items. My guess is the state before the axios request is completed, maybe? But i'm not sure how to correct for this.
If I inspect my console I see two things being output...
[]
{data: Array(20)}
Can anybody help me figure out what is going on here? Little confused here.
It looks like your API is not returning an array as you may have expected, but an object, the one you see in the console. So just change:
const bottles = res.data; to const bottles = res.data.data; and it should work.
Since you are getting {data: Array(20)} in logging this.state.bottles, that means you are looping over an object instead of an array.
In componentDidMount you need to set res.data.data instead of res.data, something like,
axios.get(`http://localhost:3000/api/v1/bottles`)
.then(res => {
const bottles = res.data.data;
this.setState({ bottles });
})
.catch(function (error) {
console.log(error);
})
I hope this resolves the issue.
Related
so my problem is, that I have two variables called stories, one of which is from the React lib and the other one in my code. The problem is, that it passes the wrong stories variable, which then gives me the error: "TypeError: stories.map is not a function", because its taking the React stories variable and not the variable I created myself. Down below is the picture where I explain it with a graphic.enter image description here
import React, {Component} from "react";
import fetch from 'isomorphic-fetch'
import Error from 'next/error'
class Index extends React.Component {
static async getInitialProps() {
let stories
try {
const response = await fetch('https://node-hnapi.herokuapp.com/news?page=1')
stories = await response.json()
} catch (err) {
console.log(err)
stories = []
}
return { stories };
}
render() {
const {stories} = this.props
if(stories.length === 0) {
return <Error statusCode={503}/>
}
return (
<div>
<h1>hacker next</h1>
<div>
{stories.map(story => (
<h2 key={story.id}>{story.title}</h2>
))}
</div>
</div>
);
}
}
export default Index;
Im making React app that shows coins' data from API.
I did it with useEffect and it works fine, but now I'm trying to do the same using Mobx.
Im trying to create a store file that gets the data from an API and stores it, then passes it to App.js and then displays the data on screen.
Im new with Mobx. Please help me resolving my Issue
This is my useEffect:
useEffect(() => {
axios.get('https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false')
.then(res => {
setCoins(res.data)
console.log(res.data)
}).catch(error => console.log(error))
}, []);
How can I convert this useEffect to Mobx in Store.js file?
For the first step I just want to display coins' name.
Thanks!
The structure should look like this one:
// Coins Store file
type Coin = {
name: string;
}
export class CointStore {
// not sure what is your coins data type, lets assume this is array
readonly coins = observable<Coin>([]);
constructor() {
makeAutoObservable(this);
}
getCoins() {
return axios.get('https://api.coingecko.com/api/v3/coins/markets')
.then(response => this.coins.replace(response.data);
}
}
...
// this is app.js file
import {observer} from 'mobx-react-lite'
import {createContext, useContext, useEffect} from "react"
import {CointStore} from './CointStore'
const CoinsContext = createContext<CointStore>()
const CoinsView = observer(() => {
const coinStore = useContext(CoinsContext);
useEffect(() => {
coinStore.getCoins()
}, []);
return (
<span>
{coinStore.coins.map(coin => <span>{coin.name}</span>)}
</span>
)
})
ReactDOM.render(
<CoinsContext.Provider value={new CointStore()}>
<CoinsView />
</CoinsContext.Provider>,
document.body
)
I'm want to render data from firestore into my react component. I updated the global state array with firestore data and it's updating but when I'm going to render that array the array shows as undefined.
I have tried using redux and the same problem happened, now used reactn but same things are happening.
import React from "react";
import {setGlobal} from "reactn";
import ReactDOM from "react-dom";
import Apps from "./Apps";
setGlobal({ names:[],})
ReactDOM.render( <Apps/>, document.getElementById("root"))
ReactDOM.render(<Apps/>, document.getElementById("root"))`
-----App.js----------
import React from "reactn";
import db from "./firebase";
class Apps extends React.Component{
componentDidMount(){
db.collection("users").get().then((snapshot)=>{
snapshot.forEach((doc)=>{
const user= {name:doc.data().name,
weight:doc.data().weight,
id:doc.id}
this.global.names.push(user)
})
})
}
render(){
///this show the data in names array of state
console.log(this.global)
//// this show undefind (its having data)
console.log(this.global.names[0])
return(
///but while rendering its not showing anything
<div>{this.global.names.map((name)=>(
<h1>weight is {name.weight} </h1>
)
)}</div>
)
}
}
export default Apps;
instead of
this.global.names.push(user)
You have to use
this.setGlobal(names: names.push(user))
I think don't use global variable in react just do something like that
class Apps extends React.Component {
constructor(props) {
super(props)
this.state = {
names: [],
}
}
componentDidMount() {
let array = [];
db.collection("users").get()
.then((snapshot) => {
snapshot.forEach((doc) => {
const user = {
name: doc.data().name,
weight: doc.data().weight,
id: doc.id
}
array.push(user)
})
})
.then(() => {
this.setState({
names : array
})
})
}
render() {
///this show the data in names array of state
console.log(this.state.names)
//// this show undefind (its having data)
console.log(this.state.names[0])
return (
///but while rendering its not showing anything
<div>{this.state.names.map((name) => (
<h1>weight is {name.weight} </h1>
)
)}</div>
)
}
}
export default Apps;
Try this and tell me if it's works :)
The code should return list of album objects in the console, but is not returning it and instead getting a 500 internal server error.
Error : enter image description here
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import axios from 'axios';
class AlbumList extends Component {
componentWillMount() {
axios.get('https://rallycoding.herokuapp.com/api/music_albums')
.then(function(response){
console.log(response);
})
}
render(){
return(
<View>
<Text> Albums ! </Text>
</View>
);
}
}
export default AlbumList;
can u try this,
axios({
method: 'get',
url: 'https://rallycoding.herokuapp.com/api/music_albums',
}).then(response => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
If API return 500 it means error on server side. Not on React-native or front-end Side
I was watching the exact same course and had this problem. As you can see if you read through the questions there, it appears that React Native has some compatibility issues with axios.
My problem was fixed by doing this:
componentWillMount() {
fetch("https://rallycoding.herokuapp.com/api/music_albums")
.then(response => response.json())
.then(data => console.log(data));
}
So this is index.js (my entry point) and I'm loading the json data here
import React from 'react';
import ReactDOM from 'react-dom';
import fetch from 'isomorphic-fetch';
import {Filter} from './src/filter';
fetch('./pizza.json')
.then(function(response) {
return response.json()
}).then(function(json) {
console.log('parsed json', json)
}).catch(function(ex) {
console.log('parsing failed', ex)
});
ReactDOM.render(<Filter />, document.querySelector('.content'));
Now in filter.js where I want to render the contents of the page, I'm not sure how to use the loaded data in index.js, here in filter.js
import React, {Component} from 'react';
export class Filter extends Component {
render() {
return (
<div>
<h1> Pizza Search App </h1>
</div>
);
}
}
I'm new at React.js and am trying to learn, having trouble understand basic react.js fundamentals, help!
You should do the fetching in Filter
import React, { Component } from 'react';
import fetch from 'isomorphic-fetch';
export class Filter extends Component {
state = {
data: null
}
componentWillMount() {
fetch('./pizza.json')
.then(function (response) {
return response.json()
}).then(function (json) {
console.log('parsed json', json)
this.setState(() => ({ data: json }))
}).catch(function (ex) {
console.log('parsing failed', ex)
});
}
render() {
const { data } = this.state
if(!data){
return <div>Loading...</div>
}
return (
<div>
<h1> Pizza Search App </h1>
(use data here...)
</div>
);
}
}
Alex is correct except you need to set the state once you've got the response:
EDIT: I missed that he had another link in his promise chain down there... either way, you only need the one. Like so:
componentWillMount() {
fetch(...).then(res => this.setState({data: res.json()})).catch(....
Also, you need to 'stringify' the json in order to display it in the render method of your component. You're not able to display raw objects like that. Sooo... you'll need to do something like
...
render() {
const { data } = this.state
return (
<div>
<pre>
<code>
{JSON.stringify(data, null, 2)} // you should also look into mapping this into some kind of display component
</code>
</pre>
</div>
)
}