I want to consume restful api in react application via bootstrap. But I can't mapping correctly. I believe that the problem is brackets. But I couldn't figure out. (ignore my div part if I can mapping, I will update that part.)
My restful api: https://api.coindesk.com/v1/bpi/currentprice.json
Restful api Json formatted:
{
"time":{
"updated":"Jun 2, 2022 08:38:00 UTC",
"updatedISO":"2022-06-02T08:38:00+00:00",
"updateduk":"Jun 2, 2022 at 09:38 BST"
},
"disclaimer":"This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org",
"chartName":"Bitcoin",
"bpi":{
"USD":{
"code":"USD",
"symbol":"$",
"rate":"29,941.3155",
"description":"United States Dollar",
"rate_float":29941.3155
},
"GBP":{
"code":"GBP",
"symbol":"£",
"rate":"23,980.6882",
"description":"British Pound Sterling",
"rate_float":23980.6882
},
"EUR":{
"code":"EUR",
"symbol":"€",
"rate":"28,094.2357",
"description":"Euro",
"rate_float":28094.2357
}
}
}
My App.js
import React, {Component} from 'react';
import Lists from './example/lists';
class App extends Component {
render() {
return (
<Lists lists={this.state.lists} />
)
}
state = {
lists: {}
};
componentDidMount() {
fetch('https://api.coindesk.com/v1/bpi/currentprice.json')
.then(res => res.json())
.then((data) => {
this.setState({ lists: data })
})
.catch(console.log)
}
}
export default App;
My list.js:
import React from 'react'
const Lists = ({lists}) => {
return (
<div>
<center><h1>Exchange</h1></center>
{lists.map((list) => (
<div class="card">
<div class="card-body">
<h5 class="card-title">{list.time}</h5>
<h5 class="card-title">{list.bpi}</h5>
</div>
</div>
))}
</div>
)
};
export default Lists
The json is not an array therefore no you do not need to map through it. Remove the map from the List component.
import React from 'react'
const Lists = ({lists}) => {
return (
<div>
<center><h1>Exchange</h1></center>
<div class="card">
<div class="card-body">
<h5 class="card-title">{lists.time}</h5>
<h5 class="card-title">{lists.bpi}</h5>
</div>
</div>
</div>
)
};
export default Lists
I am not sure your json is complete but, since your json is returning an object, you cannot use map or any loop. You just need to display the data without looping
Related
I'm using react to create a web-app that has to be static so no API calls and I need to store some data client-side (I'm currently just using a single JSON file as it's really not large) but I'm struggling to pass images down, I'm storing the references as strings in the JSON file and passing them to the props but I'm getting all sorts of errors. Is there a better or more practical way to do this?
Code (I've added a variable to imitate the JSON structure):
const HomePage = () => {
let projectInfo: ProjectInfo = {
title: "Project",
description:
"A progressive web app.",
imgURL: "./TODO", //<- HERE
mainColour: "#323232",
secondaryColour: "#464646",
};
return (
<div id="carousel-container">
<Carousel labels={["1"]}>
<ProjectPanel info={projectInfo} />
</Carousel>
</div>
);
};
export default HomePage;
interface IProjectPanelProps {
info: ProjectInfo;
}
const ProjectPanel = (props: IProjectPanelProps) => {
return (
<div className="project-panel">
<h2>{props.info.title}</h2>
<p>{props.info.description}</p>
<img src={/* ?? */} alt=""></img>
</div>
);
};
You can use base64 images to store them.
See this post https://stackoverflow.com/a/42399865/1356340 for examples of how to use binary images in React.
You can import your image in your home page as a variable and pass that variable to your child component.
import myImage from 'your_image_path';
const HomePage = () => {
let projectInfo: ProjectInfo = {
title: "Project",
description:
"A progressive web app.",
imgURL: myImage
mainColour: "#323232",
secondaryColour: "#464646",
};
return (
<div id="carousel-container">
<Carousel labels={["1"]}>
<ProjectPanel info={projectInfo} />
</Carousel>
</div>
);
};
export default HomePage;
interface IProjectPanelProps {
info: ProjectInfo;
}
const ProjectPanel = (props: IProjectPanelProps) => {
return (
<div className="project-panel">
<h2>{props.info.title}</h2>
<p>{props.info.description}</p>
<img src={info.imgURL} alt=""></img>
</div>
);
};
The following simple React component is importing a JSON file (data.js) as an object and list the items inside it.
List.js
import React from 'react'
import jsonResponse from './data'
function ZooList ({ setID }) {
const setURL = (e) => {
window.history.pushState(null, null, '/' + e)
setID(e)
}
const list = jsonResponse.animals.map((item) => {
return (
<li key={item.id}>
<div>
<img
src={item.image_url}
alt={item.name}
onClick={() => setID(item.id)}
/>
<h3>{item.name}</h3>
<p>
<b>Distribution</b>: {item.distribution}
</p>
<button onClick={() => setURL(item.id)}>More...</button>
</div>
</li>
)
})
return (
<ul>
{list}
</ul>
)
}
export default List
Now in the above page, if you click on button "More...", it calls another React component called Tile.js as fallow:
Tile.js
import React from 'react'
import jsonResponse from './data'
function Tile ({ setID, newID }) {
const clearURL = (e) => {
window.history.pushState(null, null, '/')
setID(null)
}
return (
<div>
<div>
<img
src={jsonResponse.animals[newID].image_url}
alt={jsonResponse.animals[newID].name}
/>
<h2>{jsonResponse.animals[newID].name}</h2>
<p><b>Distribution</b>: {jsonResponse.animals[newID].distribution}</p>
<StyledParagraph>{jsonResponse.animals[newID].details.long}</StyledParagraph>
<button onClick={() => clearURL(null)}>Back to overview</button>
</div>
</div>
)
}
export default Tile
The problem is that the second component is also importing the JSON file (data.js).
How can I avoid importing the data.js twice?
Generally, what would be a better way to write this app?
Imports are cached, so if you return directly a JSON with import jsonResponse from './data', the first component will import it, while the second will get it from import cache;
You can try for example, to export an instance of a class, change one of its property and then check that property in another component that make use of that import.
A ready-to-pick and very common usage example of that cache is the configureStore of react-boilerplate: it exports the store instance so whatever component import it will refer to the same store.
I have problem with displaying pagination. I'm using Wordpress REST API to fetch my posts
Here is my code:
import React, { Component } from "react";
import "./App.css";
class App extends React.Component {
constructor() {
super();
this.state = {
items: [],
totalPages: '',
nextPage: '',
};
this._loadData = this._loadData.bind(this);
}
componentDidMount() {
const url = 'http://localhost/wp-json/wp/v2/';
this._loadData(url);
}
_loadData(url) {
request.get(url).then((response) => {
this.setState({
items: response.body.items.data,
totalPages: response.body.items.last_page,
nextPage: response.body.items.next_page_url
});
});
}
render() {
let items = _.map(this.state.items, (item) => {
return (
<div key={item.id}>
<div className="content">
<span>
{item.type}
</span>
</div>
</div>
)
});
return (
<div>
{items}
</div>
<div>
<a href="#0" onClick={this._loadData(this.state.nextPage)}/>Next
</div>
}
}
export default App;
I need help beacuse I can not figure out where the problem is. I would appreciate some tutorial or something like that.
Your WordPress's REST API Endpoint isn't correct.
When you fetching data from http://localhost/wp-json/wp/v2/ using GET method, it will returns only the namespaces and routes.
If you would like to pull posts or pages, should use path like this.
http://localhost/wp-json/wp/v2/{post_type}
Replace {post_type} with the post type in plural word.
For example you would like to get latest posts you should request to
http://localhost/wp-json/wp/v2/posts
Also you can preview this url in your browser.
I'm new with React.js. I'm making filter by name and address but I don't know how to do this with separate components. I have main component Speakers - in this component I receive json and send this data to Filter and List. In List.js I get data and display all speaker items(all json). In Filter I want to make search by name and address. I don't know how to bind component filter and list. I'll appreciate if you help me. I know that Redux help working with data in React but I want to understand how to do this without it.
enter image description here
Speakers.js
import React, {Component} from 'react';
import Filters from './Filters';
import List from './List';
class Speakers extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: false,
items: []
}
}
componentDidMount() {
this.setState({isLoading: true});
fetch("https://randomapi.com/api/6de6abfedb24f889e0b5f675edc50deb?fmt=raw&sole")
.then(res => res.json())
.then(
(result) => {
this.setState({
items: result,
isLoading: false
});
console.log(result);
}
)
.catch(error => this.setState({ error, isLoading: false }));
}
render() {
return (
<div className="speakers">
<div className="container-fluid">
<Filters getItems={this.state} />
<List getItems={this.state} />
</div>
</div>
);
}
}
export default Speakers;
List.js
import React, {Component} from 'react';
class List extends Component {
render() {
const {items, isLoading} = this.props.getItems;
if (isLoading) {
return <p>Loading ...</p>;
}
return (
<div className="speakers__list">
<div className="row">
{items.map((item, index) => (
<div className="col-md-3" key={index}>
<div className="card form-group shadow">
<div className="card-body text-center">
<h5 className="card-title">{item.first} {item.last}</h5>
<p>{item.email}</p>
<p>{item.address}</p>
<p>{item.balance}</p>
<p>{item.created}</p>
</div>
</div>
</div>
))}
</div>
</div>
)
}
}
export default List;
Filters.js
import React, {Component} from 'react';
class Filters extends Component {
render() {
return (
<div className="filters">
<div className="alert shadow">
<form>
<div className="container-fluid">
<div className="row">
<div className="col-md-5">
<label>Name/Surname</label>
<input type="text" className="form-control" />
</div>
<div className="col-md-5">
<label>Address</label>
<input type="text" className="form-control"/>
</div>
<div className="col-md-2 align-self-center text-center">
<button className="btn btn-primary">Search</button>
</div>
</div>
</div>
</form>
</div>
</div>
);
}
}
export default Filters;
One way to move forward (possibly the best way, IMO) is this:
Come up with a data model to describe a single "filter". This could be as simple as an object that describes a name string and an address string that items need to be filtered using. The design of this is up to you; pick whatever works out best.
Then, build two sets of behavior into Speakers:
The ability to receive filtration instructions from Filters. You can achieve this by writing a function in Speakers that acts as a callback function when something changes in Filters. Pass this function as a prop to Filters and have Filters call it when its state changes (meaning, when you get user interaction).
The ability to send this filter object to List. Every time the callback function is called, have Speakers send it down to List. You can achieve this by storing what Filters sends back in Speakers' state and passing that state item down to List as a prop. That should update List's props every time Filters calls the callback function and thus affects Speakers' state.
Then, build behavior in List such that it changes its rendering behavior based on this filter object. Make sure to detect props updates so that it works on the fly.
I've been struggling with this for a couple days, and any help would be appreciated.
In this component, I have tried to do an HTTP call to my server and database. After parsing the response, using JSON.parse, I am getting back a correctly formed JSON object. I then want to map through that object and for each return a new component (called HistoryItem).
The code below attempts to do this by placing the object into the component state, but it is causing an infinite refresh loop. Previously I had tried a functional component.
The original iteration of this component did work. But it pulled a static JSON object from my client side files. Therefore, I am confident code works without the http call.
It seems to me I am doing something wrong with the async, which is disallowing the JSON object received asynchronously from being rendered.
Below is the main component. Note the component imports the username from redux. This feeds the HTTP call, so that it retrieves only records associated with the logged in user. Again, everything looks fine on the server/database end...
import React, {Component} from 'react';
import style from './history.css';
import HistoryItem from './HistoryItem/historyItem';
import data from '../../config/fakermyhistory.json';
import {Link} from 'react-router-dom';
import {connect} from 'react-redux';
import axios from 'axios';
class History extends Component {
constructor(props) {
super(props);
this.state = {
compiledList:[]
}
}
getData(){
this.state.compiledList.map((call, i) => {
const shaded = (call.rated) ? 'lightgrey' : 'white';
console.log("shaded", shaded);
return(
<Link to={`/reviewpage/${call._id}`} key={call._id}
style={{ textDecoration: 'none', color:'lightgrey'}}>
<div style={{backgroundColor:shaded}}>
<hr/>
<HistoryItem call={call}/>
</div>
</Link>
)
})
}
render(){
axios.post('/api/history', {username: this.props.username})
.then((res) => {
const array = JSON.parse(res.request.response);
this.setState({compiledList: array})
console.log("res", array);}
).catch((err) => console.log("err", err));
return (
<div className={style.container}>
<div className={style.historyHeader}>
<div className={style.historyHeaderText}>
Your Call History
</div>
</div>
<div className={style.historyList}>
{this.getData()};
</div>
</div>
)
}
}
const mapStateToProps = state => {
return {
username:state.auth.username
};
}
export default connect(mapStateToProps, null)(History);
Thanks in advance if you can help.
Here is another version using it as a functional component. Also doesn't render (although no errors on this one)
import React, {Component} from 'react';
import style from './history.css';
import HistoryItem from './HistoryItem/historyItem';
import data from '../../config/fakermyhistory.json';
import {Link} from 'react-router-dom';
import {connect} from 'react-redux';
import axios from 'axios';
const History =(props)=> {
const getData=(props)=>{
console.log("props", props);
axios.post('/api/history', {username: props.username})
.then((res) => {
const array = JSON.parse(res.request.response);
console.log("array", array);
array.map((call, i) => {
const shaded = (call.rated) ? 'lightgrey' : 'white';
console.log("shaded", shaded);
return(
<Link to={`/reviewpage/${call._id}`} key={call._id}
style={{ textDecoration: 'none', color:'lightgrey'}}>
<div style={{backgroundColor:shaded}}>
<hr/>
<HistoryItem call={call}/>
</div>
</Link>
)
})
}
).catch((err) => console.log("err", err));
}
return (
<div className={style.container}>
<div className={style.historyHeader}>
<div className={style.historyHeaderText}>
Your Call History
</div>
</div>
<div className={style.historyList}>
{getData(props)};
</div>
</div>
)
}
const mapStateToProps = state => {
return {
username:state.auth.username
};
}
export default connect(mapStateToProps, null)(History);
Instead of calling axios in render function, try to invoke it from componentDidMount.
This will help you prevent the infinite loop.
To return the components rendered within the map function, it was necessary to add a "return" command before the map function was called:
return array.map((call, i) => {...