I'm trying to use flickr api to fetch public photos and create an image carousel with them but seems it does not want to get photos in the beginning. Since I'm new to React, it is really hard to figure out what I'm doing wrong here so any kinda help will be appreciated.. Thank you.
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
import _ from 'lodash';
import Button from './components/button';
const urlArr = [];
const apiKey = "YOUR_API";
const userId = "YOUR_ID";
const url = `https://api.flickr.com/services/rest/?method=flickr.people.getPublicPhotos&api_key=${apiKey}&user_id=${userId}&format=json&nojsoncallback=1`;
class App extends Component {
constructor(props) {
super(props);
this.state = { urlArr: [] };
axios.get(url)
.then(function(photoData) {
_.forEach(photoData.data.photos.photo, (photo) => {
// this.setState({ urlArr: `https://farm6.staticflickr.com//${photo.server}//${photo.id}_${photo.secret}_z.jpg` });
urlArr.push(`https://farm6.staticflickr.com//${photo.server}//${photo.id}_${photo.secret}_z.jpg`);
});
this.setState({ urlArr });
});
}
render() {
return (
<div>
<Button />
</div>
);
}
};
ReactDOM.render(<App/>, document.querySelector('.container'));
Code above returns 'TypeError: Cannot read property 'setState' of undefined' and I'm not quite sure what that means..
You're calling the setState() in a callback function of a Promise.
The error is because the this is not the React Component.
You should use an arrow function or bind the React Component instance to your callback function.
For example:
axios.get(url)
.then((photoData) => {
_.forEach(photoData.data.photos.photo, (photo) => {
// this.setState({ urlArr: `https://farm6.staticflickr.com//${photo.server}//${photo.id}_${photo.secret}_z.jpg` });
urlArr.push(`https://farm6.staticflickr.com//${photo.server}//${photo.id}_${photo.secret}_z.jpg`);
});
this.setState({ urlArr });
});
Or:
axios.get(url)
.then(function(photoData) {
_.forEach(photoData.data.photos.photo, (photo) => {
// this.setState({ urlArr: `https://farm6.staticflickr.com//${photo.server}//${photo.id}_${photo.secret}_z.jpg` });
urlArr.push(`https://farm6.staticflickr.com//${photo.server}//${photo.id}_${photo.secret}_z.jpg`);
});
this.setState({ urlArr });
}.bind(this));
Related
I am trying to fetch data from firebase. I am able to get the data and update the state, but state returns undefined after render in my React context Provider. I have tried to use some of the Life cycle method like componentWillMount or calling my fetchData function my the constructor function , since it get called before render, but none is working. Below is my code.
import React, { Component } from 'react';
import { dataDB, productDetail } from './data';
import { db } from './config/fbConfig'
import { TimerSharp } from '#material-ui/icons';
const ProductContext = React.createContext();
class ProductProvider extends Component {
constructor(props) {
super(props)
this.state = {
products: []
}
this.fetchData()
}
fetchData = () => {
db.collection("projects")
.get()
.then(querySnapshot => {
const data = querySnapshot.docs.map(doc => doc.data());
console.log(data); //successfully returns the data
// this.setState({ projects: data });
this.setState(() => {
return {
projects: data
}
})
console.log(this.state.products) // successfully returns the data and update the state
});
}
render() {
console.log(this.state.products) // returns empty arr and I need it to return the updated state with data
return (
<ProductContext.Provider value={{
...this.state
}}>
{this.props.children}
</ProductContext.Provider>
)
}
}
const ProductConsumer = ProductContext.Consumer;
export { ProductProvider, ProductConsumer };
The issue is this.state.products get called before calling data in firebase. Please how can I be able to get data after render.
In fetchData() you set the attribute this.state.projects but in render you log this.state.products
I can't get my api data from https://randomuser.me/api/
But when I'm using another api like http://dummy.restapiexample.com/api/v1/employees it works.
The error:
import React from "react";
import "./App.css";
import Start from "./start";
function App() {
return (
<div className="App">
<Start />
</div>
);
}
export default App;
start.js
import React, { Component } from "react";
import Axios from "axios";
class Start extends Component {
constructor(props) {
super(props);
this.state = {
results: []
};
}
componentDidMount() {
Axios.get("https://randomuser.me/api/").then(res => {
const results = res.data;
this.setState({ results });
console.log(results);
});
}
render() {
return (
<div>
{this.state.results.map(result => {
return <div>{result.id}</div>;
})}
</div>
);
}
}
export default Start;
Problem is that http://dummy.restapiexample.com/api/v1/employees returns array while https://randomuser.me/api/ returns object. Try changing to
componentDidMount() {
Axios.get("https://randomuser.me/api/").then(res => {
const results = res.data.results;
this.setState({ results });
console.log(results);
});
}
You have to use res.data.results. It comes in results object.
Please check your JSON data
last line you missed the "}]" typo error in http://dummy.restapiexample.com/api/v1/employees
componentDidMount() {
Axios.get("http://dummy.restapiexample.com/api/v1/employees").then(res => {
const results = res.data;
this.setState({ results: results });
});
}
I'm new to react and I am trying to fetch data from an API and pass the data to a child component. I've passed the data to the state on my parent component, however, when I pass it to the child component as props it logs as an empty array. I'm sure there is something simple I am overlooking but I don't know what, my code is below
PARENT COMPONENT
import React, {Component} from 'react';
import Child from '../src/child';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
properties: []
}
}
getData = () => {
fetch('url')
.then(response => {
return response.text()
})
.then(xml => {
return new DOMParser().parseFromString(xml, "application/xml")
})
.then(data => {
const propList = data.getElementsByTagName("propertyname");
const latitude = data.getElementsByTagName("latitude");
const longitude = data.getElementsByTagName("longitude");
var allProps = [];
for (let i=0; i<propList.length; i++) {
allProps.push({
name: propList[i].textContent,
lat: parseFloat(latitude[i].textContent),
lng: parseFloat(longitude[i].textContent)
});
}
this.setState({properties: allProps});
});
}
componentDidMount = () => this.getData();
render () {
return (
<div>
<Child data={this.state.properties} />
</div>
)
}
}
export default App;
CHILD COMPONENT
import React, {Component} from 'react';
class Child extends Component {
initChild = () => {
console.log(this.props.data); // returns empty array
const properties = this.props.data.map(property => [property.name, property.lat, property.lng]);
}
componentDidMount = () => this.initChild();
render () {
return (
<div>Test</div>
)
}
}
export default Child;
Change the componentDidMount in the child to componentDidUpdate.
The componentDidMount lifecycle method is called only once in the starting. Whereas, the componentDidUpdate lifecycle method gets called whenever there is a change in the state of the application. Since api calls are asynchronous, the initChild() function is already called once before the api call's results are passed to the child.
You can use conditional rendering
import React, {Component} from 'react';
class Child extends Component {
initChild = () => {
if(this.props.data){
const properties = this.props.data.map(property => [property.name, property.lat, property.lng]);
}
}
componentDidMount = () => this.initChild();
render () {
return (
<div>Test</div>
)
}
}
export default Child;
trying to pass data from an api call to a component, but after the api call the data becomes undefined. im fairly new at react so any help would be greatly appreciated Thanks! all the classes are below, i didnt include the form componenet but it gets the data just fine
App.js
import React, { Component } from "react";
import axios from "axios";
import ShowtimeList from "./components/ShowtimeList";
import Form from "./components/Form";
import "./App.css";
class App extends Component {
constructor(props) {
super(props);
this.state = {
isFetching: true
};
this.getShowtimes = this.getShowtimes.bind(this);
}
getShowtimes(event) {
event.preventDefault();
const startDate = event.target.startDate.value;
const numDays = event.target.numDays.value;
const zipCode = event.target.zipCode.value;
const radius = event.target.radius.value;
const unit = event.target.units.value;
let showtimes = {};
const API_KEY = "<API-KEY>";
const call =
"http://data.tmsapi.com/v1.1/movies/showings?startDate=" +
startDate +
"&numDays=" +
numDays +
"&zip=" +
zipCode +
"&radius=" +
radius +
"&units=" +
unit +
"&api_key=" +
API_KEY;
this.setState({ isFetching: !this.state.isFetching });
axios
.get(call)
.then(function(response) {
console.log(response.data);
showtimes = response.data;
console.log(showtimes);
})
.catch(function(error) {
console.log(error);
});
}
renderShowtimes(showtimes) {
let times = "";
console.log(this.showtimes); ----- Undefined
if (this.showtimes != null) {
times = <ShowtimeList showtimes={this.showtimes} />;
} else {
times = "No Showtimes In Your Area";
}
return times;
}
render() {
return (
<div>
{this.state.isFetching ? (
<Form getShowtimes={this.getShowtimes} />
) : (
this.renderShowtimes()
)}
</div>
);
}
}
export default App;
ShowtimeList.js
import React, { Component } from "react";
import Showtime from "./Showtime";
class ShowtimeList extends Component {
render() {
return (
<ul>
{this.props.showtimes.map(showtime => {
return <Showtime showtime={showtime} />;
})}
</ul>
);
}
}
export default ShowtimeList;
Showtime.js
import React, { Component } from "react";
class Showtime extends Component {
render() {
return <li>{this.props.showtime}</li>;
}
}
export default Showtime;
Use state to store the showtimes and pass it down as props. Inside your state, add showtimes. Then inside your axios call instead of showtimes = response.data;, do a setState. this.setState({showtimes: response.data})
Then do <ShowtimeList showtimes={this.state.showtimes} />
You are not declaring the variable showtimes at the components scope, so that's why this.showtimes will always be undefined.
Anyway, I would recommend to store that data inside your component state.
Also in renderShowtimes you are asking for a showtime argument which you are not passing later when calling the function inside the render method.
You never set showtimes into your state. To fix this:
...
var _this = this;
axios
.get(call)
.then(function(response) {
console.log(response.data);
showtimes = response.data;
_this.setState({ showtimes: showtimes });
console.log(showtimes);
})
.catch(function(error) {
console.log(error);
});
...
Hello im new in React and im trying to play a little with React but heres one point i dont understand.
at first, fetch with axios data who return my data, the following, then i try to put them into the input fields, value(and is readonly), defaultValue is better, now i have the problem, i see nothing, the value exists when i view with firebug, the strange thing is, when i add a unneed character the input get filled by my wanted but not by default.
The very strange thing is, when i put everything in a Array and does a map function over it i have the value
the json code
{"firma":"hallo","strasse":"musterweg 7","plz":"01662"}
the js code
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
class Testx extends React.Component {
constructor(props) {
super(props);
this.state = {
data:[]
};
}
componentDidMount(){
var self = this;
axios.get('http://localhost/index.php')
.then(function (response) {
self.setState({ data: response.data});
})
.catch(function (error) {
console.log(error);
});
}
render() {
return (
<div>
<input type="text" defaultValue={this.state.data.firma}/>
</div>
);
}
}
ReactDOM.render(<Testx/>, document.getElementById('hello'));
You need to wait until the data comes by showing something loading.
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
class Testx extends React.Component {
constructor(props) {
super(props);
this.state = {
data:{}
};
}
componentDidMount(){
var self = this;
axios.get('http://localhost/index.php')
.then(function (response) {
self.setState({ data: response.data});
})
.catch(function (error) {
console.log(error);
});
}
render() {
const { data }= this.state;
if(data.firma) {
return (<div>
<input type="text" defaultValue={data.firma}/>
</div>);
}
return <div>loading...</div>;
}
}
ReactDOM.render(<Testx/>, document.getElementById('hello'));
Initially, your data state is in Array format. So this.state.data.firma doesnt work. Instead make it as empty object {}.
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
class Testx extends React.Component {
constructor(props) {
super(props);
this.state = {
data: {}
};
}
componentDidMount() {
var self = this;
axios.get('http://localhost/index.php')
.then(function (response) {
self.setState({ data: response.data});
})
.catch(function (error) {
console.log(error);
});
}
render() {
return <div>
<input type="text" defaultValue={this.state.data.firma}/>
</div>
}
}
ReactDOM.render(<Testx/>, document.getElementById('hello'));
The "code style" is outdated. Try to work with arrow functions which bind your functions, such as setState. Or bind your functions once in your constructor like this.myFunction = myFunction.bind(this) so you are able to access this. I already commented that this.state.data is declared as an array. Either change it to be an object or access an object by a specific index.
class Testx extends React.Component {
constructor(props) {
super(props);
this.state = {
data:{}
};
}
componentDidMount = () => { //Note the arrow function to bind this function
//Functions like componentDidMount are usually already bound
axios.get('http://localhost/index.php')
.then((response) => {
this.setState({ data: response.data});
})
.catch((error) => {
console.log(error);
});
}
render() {
return (
<div>
<input type="text" defaultValue={this.state.data.firma}/>
</div>
);
}
}
If your response is an array instead of an object, then try to access firma like this: this.state.data[index].firma
thanks all, special for the tips and tricks and how i can do thinks better, my questions is solved, big thanks to all for helping me in under 15 min happy
im now also found a way playing with https://facebook.github.io/react/docs/forms.html and set my state with
handleChange(event) {
var tmp = this.state.data;
tmp[event.target.id] = event.target.value
this.setState({data: tmp});
}
with modding my render
<input type="text" id="firma" value={this.state.data.firma} onChange={this.handleChange} />