This is driving me crazy. I just started playing around with react trying to learn, but i can't even make a simple API call because of a extremely weird error....
This is my code ->
import React, {Component} from 'react';
class ApiPosts extends Component {
constructor() {
super();
this.state = {
blogPosts: [],
};
}
}
componentDidMount(){
fetch('http://localhost:53595/blog/posts')
.then(results => {
return results.json();
}).then(data => {
let blogPosts = data.results.map((post) => {
return(
<div key={post.results}>
<div>{post.body}</div>
</div>
)
});
this.setState({blogPosts: blogPosts});
console.log("state", this.state.blogPosts);
})
}
render(){
return (
<div className="container2">
<div className="container1">
{this.state.blogPosts}
</div>
</div>
)
}
Lines 12 and 30 ("componentDidMount(){ & render(){") are throwing me an error showing that i haven't closed them with ';'.
The error shows up in visual studio code & fails to build my app with the following error ->
/react-website/src/ApiPosts.js: Unexpected token, expected ; (12:19)
I literally tried to close EVERYTHING in that file just to see where the error is coming from, but no luck.
Any idea?
Move componentDidMount and render function within your component class. They are outside of the class in given code snippet.
import React, {Component} from 'react';
class ApiPosts extends Component {
constructor() {
super();
this.state = {
blogPosts: [],
};
}
componentDidMount() {}
render() {}
}
You have componentDidMount and render defined outside of the component itself.
It should look like this:
import React, {Component} from 'react';
class ApiPosts extends Component {
constructor() {
super();
this.state = {
blogPosts: [],
};
}
componentDidMount() {
fetch('http://localhost:53595/blog/posts')
.then(results => {
return results.json();
}).then(data => {
let blogPosts = data.results.map((post) => {
return(
<div key={post.results}>
<div>{post.body}</div>
</div>
)
});
this.setState({blogPosts: blogPosts});
console.log("state", this.state.blogPosts);
})
}
render() {
return (
<div className="container2">
<div className="container1">
{this.state.blogPosts}
</div>
</div>
)
}
}
Related
I'm trying to call a dictionary from Django Rest Framework API to view on my frontend. Using Django backend & Reactjs frontend. Through some research looks like i'm getting this error due to the map() function only accepting arrays, while my API is returning a dictionary (I THINK SO).
How do I fix this? I'm new to javascript & apologies in advance for the messy code. Please see my App.js below:
App.js
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
todoList: [],
}
this.fetchTasks = this.fetchTasks.bind(this)
};
componentWillMount() {
this.fetchTasks()
}
fetchTasks() {
fetch('http://127.0.0.1:8000/api/api-overview')
.then(response => response.json())
.then(data =>
this.setState({
todoList: data
})
)
}
render() {
var tasks = this.state.todoList
return (
<div className="container">
{tasks.map(function (task, index) {
return (
<div className="center-column">
<div className="item-row">
<div key={index} className="centered">
<span>{task.bitcoin_symbol}</span>
</div>
</div>
</div>
)
})}
</div>
);
}
}
export default App;
API response:
You're fetching a single object, not an array. .map() is a method which run over iterables(arrays, strings, etc - objects, that can be iterated over) and creates a new output element from each input one. In react we mainly use it to convert an item to its JSX(react/html) representation. As you're working over a single object, you should access it directly:
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
bitcoinData = null
}
this.fetchBitcoinData = this.fetchBitcoinData.bind(this);
};
componentWillMount() {
this.fetchBitcoinData();
}
fetchBitcoinData() {
fetch('http://127.0.0.1:8000/api/api-overview')
.then(response => response.json())
.then(data =>
this.setState({
bitcoinData: data
});
);
}
getBitcoinRepresentation() {
var bitcoinData = this.state.fetchBitcoinData;
if (!bitcoinData) {
return <div>Loading...</div>;
}
else {
return (
<div className="container">
<div>{bitcoinData.bitcoin_symbol}</div>
<div>{bitcoinData.bitcoin_price}</div>
<div>{bitcoinData.bitcoin_dailychangeinprice}</div>
</div>
);
}
}
render() {
return getBitcoinRepresentation();
}
}
export default App;
This is the first time I am using react. I am coming from jQuery to React this feels like a big jump. If anybody can help me refactor this to work the React way I will be forever in your debt! :)
I am trying to parse an RSS feed, where I want to grab the most recent post title and link to render into a component.
https://www.npmjs.com/package/rss-parser - Using this to get the parser.
When viewing my app in the browser the async function is spitting out the rss feed into the console, which is a good start I guess!
// src/App/index.tsx
import * as React from 'react';
import * as Parser from 'rss-parser';
// Types
import { string } from 'prop-types';
let parser = new Parser();
// blueprint for the properties
interface Props {
name: string;
}
// Component state
interface State {
//feed: any[];
}
(async () => {
let feed = await parser.parseURL('https://www.reddit.com/.rss');
console.log(feed.title);
feed.items.forEach((item: { title: string; link: string; }) => {
console.log(item.title + ':' + item.link)
});
})();
export default class App extends React.Component<Props, State> {
render() {
return (
<div>
<h1>RSS Feed</h1>
<div>
<h1>item.title</h1>
item.link
</div>
</div>
);
}
}
If I understand you right, you need something like this:
export default class App extends React.Component<Props, State> {
constructor(props: {}) {
super(props);
this.state = { feed: [] };
}
async componentDidMount() {
const feed = await parser.parseURL('https://www.reddit.com/.rss');
this.setState({ feed });
}
render() {
return (
<div>
<h1>RSS Feed</h1>
this.state.feed.map((item, i) => (
<div key={i}>
<h1>item.title</h1>
item.link
</div>
))
</div>
);
}
}
I faced the same problem and solved by this. if you don't check for "undefined" value. It will show you error because react renders page 2 times and you have an undefined array of feed.items in your hand when in first render.
My index.js file:
import React from 'react'
import {render} from 'react-dom';
let Parser = require('rss-parser');
let parser = new Parser();
const CORS_PROXY = "https://cors-anywhere.herokuapp.com/";
class App extends React.Component{
constructor(props) {
super(props);
this.state = {
feed: []
};
}
async componentDidMount() {
const feed = await parser.parseURL(CORS_PROXY + 'https://www.reddit.com/.rss');
this.setState(feed)
}
render() {
return (
<div>
<h1>Blog Posts</h1>
{this.state.items && this.state.items.map((items, i) => (
<div key={i}>
<h1>{items.title}</h1>
{items.link}
</div>
))}
</div>
);
}
}
render(
<App />,
document.getElementById("root")
)
I used react.js to connect the api.
And i want to show the identifier on the page.
Here is response to console.log(this.state.weathers.cwbopendata)
After i console.log(this.state.weathers.cwbopendata.identifier)
,I got the error
What should i do to show the identifier on the page?
Here is the code:
import React,{Component} from 'react';
class App extends Component {
constructor(){
super();
this.state = {
weathers: {},
};
}
componentDidMount(){
fetch('https://opendata.cwb.gov.tw/fileapi/v1/opendataapi/F-C0032-001?Authorization=CWB-BB78764B-9687-4C1C-B180-66CB616129E5&format=JSON')
.then(response=> response.json())
.then( JSON=> this.setState({weathers:JSON}))
}
render(){
return (
<div className="App">
{console.log(this.state.weathers.cwbopendata.identifier)}
</div>
);
}
}
export default App;
This is a classic problem many newcomers face. You need to add a state to let your component know that data fetching is in progress, is completed or there is an error. So the component can show real data when it successfully fetched it, until then something you can display to the UI to let users know that the App is fetching data... I'd write it something like:
import React, { Component } from "react";
class App extends Component {
constructor() {
super();
this.state = {
weathers: {},
isFetching: true
};
}
componentDidMount() {
fetch(
"https://opendata.cwb.gov.tw/fileapi/v1/opendataapi/F-C0032-001?Authorization=CWB-BB78764B-9687-4C1C-B180-66CB616129E5&format=JSON"
)
.then(response => response.json())
.then(json => this.setState({ weathers: json, isFetching: false }));
}
render() {
const { isFetching, weathers } = this.state;
return (
<div className="App">
{isFetching ? "Loading.." : weathers.cwbopendata.identifier}
</div>
);
}
}
export default App;
In your case you tried to render the data at first mount, and at this point of time weathers is just holding an empty object {}. Thus weathers.cwbopendata returns undefined, and undefined.identifier throws the error as you see in the browser console.
Initially render method is being called before componentDidMount.
By the time it was called, data hadn't been fetched yet.
So you should properly handle situation when you have empty state.
import React,{Component} from 'react';
class App extends Component {
constructor(){
super();
this.state = {
weathers: {},
};
}
componentDidMount(){
fetch('https://opendata.cwb.gov.tw/fileapi/v1/opendataapi/F-C0032-001?Authorization=CWB-BB78764B-9687-4C1C-B180-66CB616129E5&format=JSON')
.then(response=> response.json())
.then( JSON=> this.setState({weathers:JSON}))
}
render(){
return (
<div className="App">
{console.log(this.state.weathers.cwbopendata && this.state.weathers.cwbopendata.identifier)}
</div>
);
}
}
export default App;
So I'm getting this error message saying that I have a syntax error on line 24. Which is the onSearchChange line.
Please someone help me, I've been stuck on this problem for over a day now.
import React, { Component } from 'react';
import CardList from './CardList';
import SearchBox from './SearchBox';
import './App.css';
class App extends Component {
constructor() {
super()
this.state = {
robots: [],
searchfield: ''
}
}
componentDidMount() {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response=> {
return response.json();
})
.then(users => {
this.setState({ robots: users})
}
onSearchChange = (event) => {
this.setState({ searchfield: event.target.value })
}
render() {
const filteredRobots = this.state.robots.filter(robots =>{
return robots.name.toLowerCase().includes(this.state.searchfield.toLowerCase());
})
return (
<div className ='tc'>
<h1 className='f1'> RoboFriends</h1>
<SearchBox searchChange={this.onSearchChange}/>
<CardList robots={filteredRobots} />
</div>
);
}
}
export default App;
Your render function is inside componentDiDMount. Check for the opening and closing braces.
I'm currently having a problem trying to get UI to render with React. I'm using information I've received from ShopifyAPI and trying to render it to my component. I'm not sure what to do. Do I need to update the state with information returned from my API? Here's my code at the moment.
ShopifyCatalog.js
import React, { Component } from 'react';
import { Link } from 'react-router'
import styles from '../styles';
import ShopProducts from './ShopProducts'
import { getAllProducts } from '../utils/shopifyHelpers';
export default class ShopCatalog extends Component {
constructor(...args){
super(...args);
this.state = {
allProducts: []
}
}
render() {
let allProducts
getAllProducts()
.then((products) => {
return allProducts = products
})
.then((allProducts) => {
allProducts.map((product) => {
<div className='col-sm-offset-1 col-sm-2'>
<Link to={'shop/${product.id}'}>
<img src={product.images[0].src} />
<h5>{product.title}</h5>
</Link>
</div>
})
})
return (
<div style={styles.productInfo}>
{allProducts}
</div>
)
}
}
I thought it might have something to do with using promises more extensively, but I'm pretty sure it's because my state isn't updating with the information that I'm grabbing from the API. I appreciate your time, thank you.
EDIT:
I've updated my code now and it looks like this
ShopCatalog.js Updated
import React, { Component } from 'react';
import { Link } from 'react-router'
import styles from '../styles';
import ShopProducts from './ShopProducts'
import { getAllProducts } from '../utils/shopifyHelpers';
export default class ShopCatalog extends Component {
constructor(...args){
super(...args);
this.state = {
allProducts: [],
listAllProducts: []
}
}
componentDidMount() {
getAllProducts()
.then((products) => {
this.setState({
allProducts: products
})
})
}
render() {
return (
<div style={styles.productInfo}>
{this.state.allProducts.map((product) => {
<h1>{product.title}</h1>
})}
</div>
)
}
}
But it's still not rendering anything from the map of my state. Is it because map is called while there is nothing in the state? How do I work around this so map get's called and returns UI? Thank you.
Put your request in the componentDidMount lifecycle method, then update your state. Your render method is returning before your request has completed.
export default class ShopCatalog extends Component {
constructor(...args){
super(...args);
this.state = {
allProducts: []
}
}
componentDidMount() {
const _this = this;
getAllProducts()
.then((products) => {
_this.setState({ allProducts: products });
});
}
render() {
return (
<div style={styles.productInfo}>
{this.state.allProducts.map((product) => {
<div className='col-sm-offset-1 col-sm-2'>
<Link to={'shop/${product.id}'}>
<img src={product.images[0].src} />
<h5>{product.title}</h5>
</Link>
</div>
})}
</div>
)
}
}
I assume something like this, not sure specifics to your case, just giving idea how this should look like.
export default class ShopCatalog extends Component {
state = {
allProducts: []
}
getAllProducts = () => {
fetch(...API).then(response => response.json()).then(products =>
this.setState({allProducts: products}));
}
componentDidMount() {
this.getAllProducts()
}
render() {
const {allProducts} = this.state;
return (
<div>
{allProducts.map((product,key) => <div key={key}>
<span>{product.title}</span>
</div>
)}
</div>
)
}
}