Fetch API Error: Cannot read property 'map' of undefined - reactjs

I'm following this online tutorial on using Fetch to consume API data; I was able to get the application to Fetch data using the JSON url provided in the tutorial. However, I made some modifications to the code and attempted to fetch data from a different JSON file and got an error:
Here is the code:
import React, { Component } from 'react';
import {render} from "react-dom";
import Navbar from '../components/Navbar.jsx';
import Footer from '../components/Footer.jsx';
import './ClientInfo.css';
class ClientInfo extends Component {
constructor(){
super();
this.state= {
titles: []
};
}
componentWillMount(){
fetch('https://jsonplaceholder.typicode.com/todos')
.then(results => {
return results.json();
}).then(data => {
let titles = data.results.map((til) => {
return(
<div key={til.results}>
<p>{til.title} </p>
</div>
)
})
this.setState({titles: titles});
console.log("state", this.state.titles);
})
}
render() {
return (
<div>
<Navbar />
<div className="container">
<div className="clientContainer">
{this.state.titles}
</div>
</div>
<Footer />
</div>
);
}
}
export default ClientInfo
The error occurs at this line:let titles = data.results.map((til) => {. could I get some help as what am doing wrong?

data.results - not array. Array data.map

Related

Why am I getting a blank screen while following React JS?

I am following the current tutorial:
Youtube tutorial at 12:51 mins.
I expect to see bunch of posts on my screen but my screen remains blank.
It appears I have followed everything told in the tutorial.
import React, { Component } from 'react';
class Posts extends Component {
constructor(props) {
super(props);
this.state = {
posts: []
}
}
componentWillMount() {
fetch('https://jsonplaceholder.typicode.posts')
.then(res => res.json())
.then(data => this.setState({posts: data}))
}
render() {
const postItems = this.state.posts.map(post => (
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.body}</p>
</div>
));
return (
<div>
<h1>Posts</h1>
{ postItems }
</div>
);
}
}
export default Posts;
and
import React, { Component } from 'react';
import './App.css';
import Posts from './components/Posts'
class App extends Component {
render() {
return (
<div className="App">
<Posts />
</div>
);
}
}
export default App;
My browser screen remains blank and I do not see any errors on console.
What am I missing ?
Don't know about the tutorial but it looks outdated...
Here is your App.js (parent component):
import React, { Component } from 'react';
import Posts from './Posts';
export default class App extends Component {
state = { posts: [] };
//fetch the posts and store them in the state
componentDidMount() {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(posts => this.setState({ posts }))
.catch(error => console.log(error));
}
render() {
return (
<div>
{/* pass the state (posts) as props to Posts */}
<Posts posts={this.state.posts} />
</div>
);
}
}
Here is your Posts.js:
import React from 'react';
// No need for a class based comp
// destructure the props and you have all your data
const Posts = ({ posts }) => (
<div>
{posts.map(post => (
<div key={post.id}>
<h3>{post.title}</h3>
<p>{post.body}</p>
<hr />
</div>
))}
</div>
);
export default Posts;
Live Demo: https://jsfiddle.net/ctszdue9/7/
Try putting side effect/ api call inside
componentDidMount() { }
Change URL
https://jsonplaceholder.typicode.posts/
TO
https://jsonplaceholder.typicode.com/posts

Unexpected Token in react while using fetch

I am new to react and I have been learning it online.But I have some issues.Whenever I try to fetch the url it says
Syntax error: C:/xampp/htdocs/react-project/src/App.js: Unexpected token, expected ; (14:10).I have followed the same step as the video but also I am getting the problem.Here is the code
import React, { Component } from 'react';
import './App.css';
import Flat from './components/flat';
class App extends Component {
constructor(props){
super(props);
this.state={
flats:[]
}
}
componentDidMount(){
const url="https://raw.githubusercontent.com/lewagon/flats-boilerplate/master/flats.json";
fetch url()
.then(response =>response.json())
.then((data)=>{
console.log(data);
});
}
render() {
return (
<div className="app">
<div className="main">
<div className="search">
</div>
<div className="flats">
{this.state.flats.map((flat)=>{
return <Flat flat ={flat} />
})}
</div>
</div>
<div className="map">
</div>
</div>
);
}
}
export default App;
Here is the error message
I would be grateful for your help and sorry if I've done dumb mistake
It is simple syntax error.It should be :
fetch(url).then(response => response.json()).then(//dosomething)
You should replace fetch url() with fetch(url) in line 14
You can change the fetch like this way
const url="https://raw.githubusercontent.com/lewagon/flats-boilerplate/master/flats.json";
fetch(url, {
method: 'GET',
}).then(response =>response.json())
.then((data)=>{
console.log(data);
});

React API elements not displaying on page

I've been looking for about 2 hours into why I am not displaying any of the information to the page. I've console logged my response from a simple random quote api and it shows, Author: and Quote: in the console, however these are not appearing in my fields, All I am seeing is the button.
import React, { Component } from 'react';
import QuoteMachine from './Quotemachine';
const END_POINT = 'https://random-quote-
generator.herokuapp.com/api/quotes/random';
class App extends Component {
constructor(props) {
super(props);
this.state = {
quote: {
text: '',
author: ''
}
}
}
getQuote() {
fetch(END_POINT)
.then(response => response.json())
.then(response => {
this.setState = ({
quote: response
});
console.log(response);
})
}
componentDidMount() {
this.getQuote();
}
render() {
return (
<div className="App">
<div className="container">
<QuoteMachine quote= {this.state.quote} />
<button id="new-quote" className="primary-color-
background" onClick={() => this.getQuote()}>New quote</button>
</div>
</div>
);
}
}
export default App;
And then here is my Quotemachine.js
import React from 'react'
import PropTypes from 'prop-types';
const QuoteMachine = (props) => {
return (
<div className="quote-box">
<div className="text">
<span>{props.quote.text}</span>
</div>
<div className="author">
<span >{props.quote.author}</span>
</div>
</div>
);
};
QuoteMachine.propTypes = {
quote: PropTypes.object.isRequired
};
export default QuoteMachine;
It is only displaying the button, but the console.log shows
Object
author:
"Thomas Henry Huxley (1825-1895)"
quote:
"Try to learn something about everything and everything about something."
proto
:
Object
Install React Developer Tools plugin and check if your state is changing after the API call

ReactJS error TypeError: Cannot read property 'map' of undefined

I'm attempting to consume a JSON API using fetch; the error mentioned above appears on the following line: **this.state.data.map( (dynamicData,key)=>**
This is my ReactJS code with the error line in bold:
import React, { Component } from 'react';
import './App.css';
class App extends Component {
//constructor
constructor() {
super();
this.state = {
data: [],
}
} //end constructor
componentDidMount(){
return fetch('https://jsonplaceholder.typicode.com/todos')
.then((response)=>response.json())
.then((responseJson)=>
{
this.setState({
data:responseJson.todos
})
console.log(this.state.data)
})
} // end component did mount
render() {
return (
<div>
<h2>Todo:</h2>
<div>
{
**this.state.data.map( (dynamicData,key)=>**
<div>
<span> {dynamicData.userId} </span>
<span> {dynamicData.id} </span>
</div>
)
}
</div>
</div>
);
}
}
export default App;
Could I get some help as to what I'm doing wrong? Thanks in advance
import React, { Component } from "react";
import { render } from "react-dom";
class App extends Component {
state = {
data:[],
url: "https://jsonplaceholder.typicode.com/todos"
};
componentDidMount() {
fetch(this.state.url)
.then(response => response.json())
.then(data => this.setState({ data }));
}
render() {
const { data } = this.state;
data && console.log(data);
return (
<div>
{data &&
data.map(item => <div> Hello User With Id: {item.userId} </div>)}
</div>
);
}
}
render(<App />, document.getElementById("root"));
Your didMount should look like mine also, setState takes a callback so if you wanted to see what the data looked like it would be like this
this.setState({ data }, () => console.log(this.state.data))
In your render it looks like you forgot the parenthesis after the arrow function in map.
render() {
return (
<div>
<h2>Todo:</h2>
<div>
{
this.state.data.map((dynamicData,key)=> (
<div>
<span> {dynamicData.userId} </span>
<span> {dynamicData.id} </span>
</div>
))
}
</div>
</div>
);
}

How to display loaded posts with React and Redux

I'm new to React and Redux, and im trying to load posts from the WordPress REST API, and display them in my React App.
I'm using this as an example: https://github.com/jackreichert/a-wp-react-redux-theme
My action to get the posts look like this:
import axios from 'axios';
export const FETCH_POSTS = 'FETCH_POSTS';
export function fetchPosts(post_type = 'posts') {
return function (dispatch) {
axios.get(`http://localhost:8080/wp-json/wp/v2/${post_type}`)
.then(response => {
dispatch({
type: FETCH_POSTS,
payload: response.data
});
});
}
}
It's passed to the reducer, which looks like this:
import { FETCH_POSTS } from '../actions';
export default (state = [], action) => {
switch (action.type) {
case FETCH_POSTS:
return action.payload;
default :
state = '';
break;
}
return state;
}
And (though it's only one reducer) I'm combining it, because there are more reducers to follow (just like in the example), and then I'm storing it. Also pretty much the same way as the example.
Im loading everything in my Home.jsx file, which looks like this right now:
import React, { Component } from 'react';
import {connect} from 'react-redux';
import { Link } from 'react-router-dom';
import Header from '../Header';
import {fetchPosts} from '../../actions/';
class Home extends Component{
componentDidMount(){
document.title = 'Test';
}
componentWillMount() {
this.getPosts(this.props, true);
}
componentWillReceiveProps(nextProps) {
this.getPosts(nextProps);
}
getPosts(props, willMount = false) {
if (willMount) {
this.props.fetchPosts();
}
}
render() {
return(
<div>
<Header/>
<main>
<h1>Home</h1>
</main>
</div>
)
}
}
function mapStateToProps({posts}) {
return {posts};
}
export default connect(mapStateToProps, {fetchPosts})(Home);
I think my code above is right. Redux can also 'find' my posts, and logs in my console:
action FETCH_POSTS # 11:11:56.393
prev state Object {posts: ""}
action Object {type: "FETCH_POSTS", payload: Array(2)}
next state Object {posts: Array(2)}
Now I want to know: How can I simply display the posts which are loaded by Redux, in my Home.jsx file.
And after that: How can I configure the route and data, to go to a single post (but that will come later, for now I only want to know an easy but right way how to display the posts)
I have no idea about the structure of your Post object. But it should be something like this.
renderPosts() {
return _.map(this.props.posts, post => {
return (
<li className="list-group-item" key={post.id}>
{post.title}
</li>
);
});
}
Then in your render method merely call it like this.
render() {
return (
<div>
<h3>Posts</h3>
<ul className="list-group">
{this.renderPosts()}
</ul>
</div>
);
}
Also notice that I am using map helper from lodash library here. So you need to have following import statement in your component.
import _ from 'lodash';
Hope this helps. Happy coding !
If you implemented you combineReducers correctly then mapStateToPosts should be called with set of posts when it is changed.
import posts from './posts_reducer';
combineReducers({ posts });
To render posts in your Home component you need to modify the render function, see raw implementation below:
render() {
let postsElements = this.props.posts.map(p => {
return <div>p.title</div>
});
return(
<div>
<Header/>
<main>
<h1>Home</h1>
</main>
<div>
{postsElements}
</div>
</div>
)
}
You need to use this.props.posts to access your posts because react-redux maps properties from state to props object of the component using mapStateToProps function that is provided as a 1st argument when calling connect function.
To improve this you can implement you Blog component and replace div with that.
Also, review how it is implemented in the example you provided https://github.com/jackreichert/a-wp-react-redux-theme/blob/master/src/components/main.js in this file posts are rendered.
import React, { Component } from 'react';
import { connect } from 'react-redux'; // glue between react and redux
import Parser from 'html-react-parser';
import { LinkContainer } from 'react-router-bootstrap';
import { ListGroup, ListGroupItem, Image } from 'react-bootstrap';
class BlogPosts extends Component {
render() {
if (!this.props.posts) {
return (<div></div>);
}
return (
<div className="blog-items" >
<ListGroup>
{this.renderBlogPosts()}
</ListGroup>
</div>
)
};
renderBlogPosts() {
if (this.props.posts.posts) { //v1
const posts = this.props.posts.posts; // DRY
return posts.map((post, index) => {
const excerptText = JSON.stringify(post.excerpt);
const excerpt = excerptText.substring(1, excerptText.length-3);
return (
<LinkContainer className="blog-posts-link" key={post.ID} to={ "/blog/post/" + post.ID + '/'}>
{ this.getHtml(
post.ID,
(post.featured_image) ? post.featured_image : '',
post.title,
excerpt
)}
</LinkContainer>
);
});
};
const posts = this.props.posts; // DRY
return posts.map((post, index) => { // v2
return (
<div key={post.id}>
{this.getHtml(
post.id,
(post._embedded['wp:featuredmedia'])
? post._embedded['wp:featuredmedia'][0].media_details.sizes.thumbnail.source_url : '',
post.title.rendered,
post.excerpt.rendered
)}
</div>
);
});
};
getHtml(id, imageSrc, title, excerpt) {
return (
<ListGroupItem className="blog-posts-list-item">
{this.getImage(imageSrc, title)}
<h2 className="blog-posts-title">{ Parser(title) }</h2>
<div className="blog-posts-excerpt">{Parser(excerpt)}</div>
</ListGroupItem>
);
};
getImage(imageSrc, title) {
return (imageSrc === "")
? (<div></div>)
: (<div className="blog-posts-image-div">
<Image className="blog-posts-image" src={imageSrc} alt={title} />
</div>
);
};
};
const mapStateToProps = (state) => ({ posts: state.posts });
export default connect(mapStateToProps) (BlogPosts);

Resources