Extract slug from unsplash - json

I have a list of photos, fetched from this url https://picsum.photos/v2/list.
In this list there is slug that should be extracted, for example https://unsplash.com/photos/_h7aBovKia4.
Here is fetch thing I used
import React, {Component} from 'react';
import '../App.css';
import ImageList from "./ImageList";
class App extends Component {
constructor() {
super();
this.state = {
images: []
};
}
componentDidMount() {
fetch("https://picsum.photos/v2/list")
.then(res => res.json())
.then(data => {
this.setState({ images: data });
})
.catch(err => {
console.log('Error happened during fetching!', err);
});
}
render() {
return (
<div className="container">
<h2 className="title">Images list</h2>
<ImageList data={this.state.images}/>
</div>
)
}
}
export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.2.0/umd/react-dom.production.min.js"></script>
And here is ImageList Component
import React from "react";
import Image from "./Image";
const ImageList = props => {
const results = props.data;
let images = results.map(image => <Image url={image.url} key={image.id}/>);
return (
<ul className="img-list">{images}</ul>
);
};
export default ImageList;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.production.min.js"></script>
How can I get that slug from each photo url? without it, images aren't showing in browser, just their alts
UPD. Image Component
import React from "react";
const Image = props => {
return (
<li className="image-wrap">
<img src={props.url} alt="Something went wrong"/>
</li>
)
}
export default Image;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.4.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.4.0/umd/react-dom.production.min.js"></script>

You have to use download_url property, not url.
The url points to a Unsplash page with comments, site interface etc. The download_url however is a direct link to the image.

Related

How to implement multiple API in one component

i stuck in a project where i have to implement JSON Place Holder Post API and JSON Place Holder Comment API both API in a particular component.Actually my task is build a project like a facebook post component where user can post and comment. I implemented Post API successfully but i couldn't find any solution to use comment API. I did all thing but it's not show in my Home component.
How can i implement comment api in my home component
my console said it present but i couldn't show this
This is Home.js File
import React, { useEffect, useState } from 'react';
import Post from '../Post/Post';
import Comment from '../Comment/Comment';
import './Home.css';
const Home = () => {
const [post,setPost] = useState([]);
const [comment,setComment] = useState([]);
useEffect(()=>{
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res=>res.json())
.then(data=>setPost(data))
},[])
useEffect(()=>{
fetch('https://jsonplaceholder.typicode.com/comments')
.then(res=>res.json())
.then(data=>setComment(data))
},[])
return (
<div>
<div>
{
post.map(post=><Post post={post}></Post>)
}
</div>
<div className="main-body">
{
comment.map(comment=><Comment comment={comment}></Comment>)
}
</div>
</div>
);
};
export default Home;
This comment.js File
import React from 'react';
const Comment = (props) => {
const {name,email} = props.comment.name;
console.log(props.comment);
return (
<div>
{name}
{email}
</div>
);
};
export default Comment;
This is post.js File
import React from 'react';
import './Post.css';
const Post = (props) => {
const {title,body} = props.post;
return (
<div className="body-style">
<h1 className="name">{title}</h1>
<p>{body}</p>
</div>
);
};
export default Post;
Please help me I need solution
The structure is incorrect, in order to do that, comment should be children of post, and home will pass data to the post. Since you fetch data from 2 difference API, you need to combined it into 1 source and pass that down.
Home.js
import React, { useEffect, useState } from 'react';
import Post from '../Post/Post';
import './Home.css';
const Home = () => {
const [post,setPost] = useState([]);
const [comment,setComment] = useState([]);
const [ info, setInfo ] = useState([]);
useEffect(()=>{
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res=>res.json())
.then(data=>setPost(data))
},[])
useEffect(()=>{
fetch('https://jsonplaceholder.typicode.com/comments')
.then(res=>res.json())
.then(data=>setComment(data))
},[])
//Function to combine post and comment base on ID
const merge = (post, comment) => {
const temp = [];
post.forEach((x) => {
comment.forEach((y) => {
if (x.id === y.id) {
let cName = y.name;
let cEmail = y.email;
let cBody = y.body;
temp.push({ ...x, cName, cEmail, cBody });
}
});
});
return temp;
};
useEffect(
() => {
setInfo(merge(post, comment));
console.log(info);
},
[ post, comment ]
);
return (
<div>
{info.map((each) => <Post key={each.id} data={each} />)}
</div>
);
};
export default Home;
Post.js
import React from 'react';
import Comment from './Comment';
const Post = (props) => {
const { title, body, cEmail, cName } = props.data;
return (
<div className="body-style">
<h1 className="name">{title}</h1>
<p>{body}</p>
<Comment email={cEmail} name={cName} />
</div>
);
};
export default Post;
Comment.js
import React from 'react';
const Comment = ({ name, email }) => {
return (
<div>
{name}
{email}
</div>
);
};
export default Comment;

Passing props in react - fetching

I'm simply trying to pass props through components and render it in jsx but somehow that wouldn't work. I was searching for the problem but just cannot find it.
I'm trying pass props from this component:
import React from "react";
import "../styles/Products.css";
import ProductItem from "../items/ProductItem";
class Products extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
componentDidMount() {
fetch("../products.json")
.then(response => response.json())
.then(response => this.setState({ data: response.products }));
}
render() {
return (
<div className="products-container">
<ProductItem data={this.state.data[0]} />
</div>
);
}
}
export default Products;
to this component:
import React from "react";
import "../styles/ProductItem.css";
const ProductItem = props => {
console.log(props.data, "current");
return (
<div className="product-item">
<img src="" alt="" className="bike-image" />
<div className="active-product" />
<div className="view-details">Compare</div>
<h2>Bike</h2>
<h4>downhill bike</h4>
<p>3500 PLN</p>
</div>
);
};
export default ProductItem;
And the problem is when I'm looking in my react dev tools, props has passed properly, but when I'm trying to get to attributes of the object like props.data.id, I get an error:
Cannot read property 'id' of undefined
fetch needs some time to get the response and populate the this.state.data array. So you need to check if the this.state.data[0] value is really available or not. You can try this-
render() {
return (
<div className="products-container">
{this.state.data && this.state.data.length > 0 && <ProductItem data={this.state.data[0]} />}
</div>
);
}

Understanding React.JS JSON feed and how to parse

I've got the following code which is looping through an JSON file from an API and loops through some posts.
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
//https://alligator.io/react/axios-react/
import axios from 'axios';
export default class PostList extends React.Component {
state = {
posts: []
}
componentDidMount() {
axios.get(`https://jsonplaceholder.typicode.com/users`)
.then(res => {
const posts = res.data;
this.setState({ posts });
})
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
Pulls in post slugs from Domain
</p>
<ul>
{ this.state.posts.map(post => <li>{post.name} - {post.username} </li>)}
</ul>
</div>
)
}
}
This works fine, and gets the information which was needed.
Now, in my test JSON file, the format is as follows:
https://jsonplaceholder.typicode.com/users
But in my actual JSON file from WordPress Rest API, we have another item, named core_layout:
JSON image
My issue is, trying to use the same code such as {post.name}does not get the information needed such as core_layout->image->name.
Is there an easy way around this?
Thanks all!
EDIT:
Tried the answers below, but still no luck, get the error TypeError: Cannot read property 'map' of undefined:
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
//https://alligator.io/react/axios-react/
import axios from 'axios';
export default class PostList extends React.Component {
state = {
posts: [],
coreLayout: {}
}
componentDidMount() {
axios.get(`https://jsonplaceholder.typicode.com/users`)
.then(res => {
// const posts = res.data;
//this.setState({ posts });
const { posts, core_layout: coreLayout } = res.data;
this.setState({ posts, coreLayout });
})
}
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Welcome to React</h1>
</header>
<p className="App-intro">
Pulls in post slugs from domain
</p>
<ul>
{ this.state.posts.map(post => <li>{post.name} - {post.core_layout.image.name}</li>)}
</ul>
</div>
)
}
}
EDIT 2:
Tried the below: This gets the title, but again, not the actual corelayout I need.
import React, { Component } from 'react';
class App extends Component {
constructor() {
super();
this.state = {
movies: []
}
}
componentDidMount() {
let dataURL = "http://zinsseruk.com/wp-json/wp/v2/posts?per_page=1";
fetch(dataURL)
.then(res => res.json())
.then(res => {
this.setState({
movies: res
})
})
}
render() {
let movies = this.state.movies.map((movie, index) => {
return <div key={index}>
<p><strong>Title:</strong> {movie.title.rendered}</p>
<p><strong>Title:</strong> {movie.core_layout.acf_fc_layout}</p>
</div>
});
return (
<div>
<h2>Star Wars Movies</h2>
{movies}
</div>
)
}
}
export default App;
Replace const posts = res.data; with const posts = res.data.core_layout;. Then you'll get an array similar to what you have in your test file.
I think you need to understand the JSON structure you receive from the API. Where is located core_layout property? Inside each post property as a children?
So in the posts loop you can use post.core_layout.image.name for image name, for example (and so on with other properties).
If core_property is at the root of the data you receive, you can load it inside your state like so:
state = {
posts: [],
coreLayout: {}
}
componentDidMount() {
axios.get(`https://jsonplaceholder.typicode.com/users`)
.then(res => {
// This is equivalent of doing
// const posts = res.data.posts
// const coreLayout = res.data.core_layout
const { posts, core_layout: coreLayout } = res.data;
this.setState({ posts, coreLayout });
})
}
Then use it in your code by using local component state:
render() {
...
// For example image name:
console.log('image name', this.state.coreLayout.image.name)
...
}

React-Native: Type Error when parsing JSON

I was trying to implement a News App. It should show a list of news headlines on start with thumbnail image and description and then on clickinh the url should be opened in browser. But, i am stuck on halfway getting a Type Error.
Here are the codes of my NewsList and NewsDetail files.
NewsList.js
import React, { Component } from 'react';
import { ScrollView } from 'react-native';
import axios from 'axios';
import NewsDetail from './NewsDetail';
class NewsList extends Component {
constructor(props) {
super(props);
this.state = {
news: []
};
}
//state = {news: []};
componentWillMount() {
axios.get('https://newsapi.org/v2/top-headlines?country=in&apiKey=MYAPIKEY')
.then(response => this.setState({news: response.data }));
}
renderNews() {
return this.state.news.map(newsData =>
<NewsDetail key={newsData.title} newsData={newsData} />
);
}
render() {
console.log("something",this.state);
return (
<ScrollView>
{this.renderNews()}
</ScrollView>
);
}
}
export default NewsList;
NewsDetail.js
import React from 'react';
import { Text, View, Image, Linking } from 'react-native';
import Card from './Card';
import CardSection from './CardSection';
import Button from './Button';
import NewsList from './NewsList';
const NewsDetail =({ newsData }) => {
const { title, description, thumbnail_image, urlToImage, url } = newsData;
const { thumbnailStyle,
headerContentStyle,
thumbnailContainerStyle,
headerTextStyle,
imageStyle } =styles;
return(
<Card>
<CardSection>
<View>
<Image
style={thumbnailStyle}
source={{uri: urlToImage}}
/>
</View>
<View style={headerContentStyle}>
<Text style={headerTextStyle}>{title}</Text>
<Text>{description}</Text>
</View>
</CardSection>
<CardSection>
<Image
style={imageStyle}
source={{uri:urlToImage}}
/>
</CardSection>
<CardSection>
<Button onPress={() =>Linking.openURL(url)} >
ReadMore
</Button>
</CardSection>
</Card>
);
};
export default NewsDetail;
StackTrace of the Error i am getting
TypeError: this.state.news.map is not a function
This error is located at:
in NewsList (at App.js:11)
in RCTView (at View.js:78)
in View (at App.js:9)
in App (at renderApplication.js:35)
in RCTView (at View.js:78)
in View (at AppContainer.js:102)
in RCTView (at View.js:78)
in View (at AppContainer.js:122)
in AppContainer (at renderApplication.js:34) NewsList.renderNews
NewsList.js:21:31 NewsList.proxiedMethod
createPrototypeProxy.js:44:29 NewsList.render
NewsList.js:31:18 NewsList.proxiedMethod
createPrototypeProxy.js:44:29 finishClassComponent
ReactNativeRenderer-dev.js:8707:30 updateClassComponent
ReactNativeRenderer-dev.js:8674:11 beginWork
ReactNativeRenderer-dev.js:9375:15 performUnitOfWork
ReactNativeRenderer-dev.js:11771:15 workLoop
ReactNativeRenderer-dev.js:11839:25 Object.invokeGuardedCallback
ReactNativeRenderer-dev.js:39:9
App.js
import React from 'react';
import { AppRegistry, View } from 'react-native';
import Header from './header';
import NewsList from './NewsList';
//create component
const App = () => {
return(
<View style={{ flex:0 }}>
<Header headerText={'Headlines'} />
<NewsList />
</View>);
}
export default App;
AppRegistry.registerComponent('news', () => App);
The error you're getting - TypeError: this.state.news.map is not a function, means that news is not an array.
By checking your api response you should do:
this.setState({news: response.data.articles }).
You can actually go to https://newsapi.org/v2/top-headlines?country=in&apiKey="MY_API_KEY" in the browser or use a tool like curl or Postman to check what the response is. The data response is an object, but you need an array. articles is most likely the property you are after.
You may also want to check that this is an array and update what is displayed appropriately.
.then(response => {
const news = response.data.articles;
if (Array.isArray(news)) {
this.setState({ news });
} else {
this.setState({ errorMessage: 'Could not load any articles' });
}
});

Display API data using Axios and a list in React

I'm attempting to make a request to this https://www.themoviedb.org/documentation/api API in a React project and then display JSON data on my site.
I'm using Axios to make the request and I have been able to make the request and get the appropriate JSON data and console.log it or view it in the React tools in Firefox. However, I am having difficulty displaying the data in a ul. Initially I had an error pertaining to having a unique key for each list item, and I have since resolved that (or so I believe).
Here's my request and how I am attempting to render the data:
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import axios from "axios";
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
posts: []
}
}
componentDidMount() {
axios.get(`https://api.themoviedb.org/3/movie/now_playing?api_key=*apikeyhere*&language=en-US&page=1`)
.then(res => {
const posts = res.data.results.map(obj => [obj.title, obj.overview]);
this.setState({ posts });
});
}
/* render() {
return (
<div>
<h1>Movie API data</h1>
<ul>
{this.state.posts.map(post =>
<li key={post.toString()}>{post.title}</li>
)}
</ul>
</div>
);
}
}
*/
render() {
return (
<ul>
{this.state.posts.map(function(post, index){
return (
<div key={index}>
<h1>{post.title}</h1>
<p>{post.overview}</p>
</div>
)
}
)}
</ul>
);
}
}
As you can see I attempted multile approaches to rendering this. What's wrong with my code and why isn't the JSON data rendering in the ul on my site?
I think, you have an error inside success fuction ({title: obj.title, overview: obj.overview})
componentDidMount() {
axios.get(`https://api.themoviedb.org/3/movie/now_playing?api_key=*apikeyhere*&language=en-US&page=1`)
.then(res => {
const posts = res.data.results.map(obj => ({title: obj.title, overview: obj.overview}));
this.setState({ posts });
});
}