I have a JSON file:
[
{
"id": 1,
"text": "Hello",
"availability": false
},
{
"id": 2,
"text": "Hello",
"availability": true
}
]
What I would like to achieve is for the text to automatically change from hello to goodbye when availability : false. If availability : true then I would like it to stay the same displaying 'Hello'.
This is my code so far:
import React, { Component } from 'react';
import './styles.css'
class GetOnlinePosts extends Component {
constructor(props){
super(props);
this.state = {
error : null,
isLoaded : false,
posts : []
};
}
componentDidMount(){
fetch("https://api.myjson.com")
.then( response => response.json())
.then(
(result) => {
this.setState({
isLoaded : true,
posts : result
});
},
(error) => {
this.setState({
isLoaded: true,
error
})
},
)
}
render() {
const {error, isLoaded, posts} = this.state;
const orderedPosts = [...posts.filter((post) => post.availability), ...posts.filter((post) => !post.availability)]
if(error){
return <div>Error in loading</div>
}else if (!isLoaded) {
return <div>Loading ...</div>
}else{
return(
<div>
<div className="tiles">
{
orderedPosts.map(post => (
<div key={post.id}>
<div className="tile">
<p className="greeting">{post.text}</p>
</div>
</div>
))
}
</div>
</div>
);
}
}
}
export default GetOnlinePosts;
Any help on changing the text from 'Hello' to 'Goodbye' when availability : false and keeping the text 'Hello' when availability : true would be great. thanks in advance
Please add condition to map
<p className="greeting">{post.availability ? post.text : 'Goodbye'}</p>
Please changes this line
import React, { Component } from 'react';
import './styles.css'
class GetOnlinePosts extends Component {
constructor(props){
super(props);
this.state = {
error : null,
isLoaded : false,
posts : []
};
}
componentDidMount(){
fetch("https://api.myjson.com")
.then( response => response.json())
.then(
(result) => {
this.setState({
isLoaded : true,
posts : result
});
},
(error) => {
this.setState({
isLoaded: true,
error
})
},
)
}
render() {
const {error, isLoaded, posts} = this.state;
const orderedPosts = [...posts.filter((post) => post.availability), ...posts.filter((post) => !post.availability)]
if(error){
return <div>Error in loading</div>
}else if (!isLoaded) {
return <div>Loading ...</div>
}else{
return(
<div>
<div className="tiles">
{
orderedPosts.map(post => (
<div key={post.id}>
<div className="tile">
<p className="greeting">{post.availability ? post.text : 'Goodbye'}</p> // Change this line
</div>
</div>
))
}
</div>
</div>
);
}
}
}
export default GetOnlinePosts;
Somewhere after fetching, map the results like this:
const processPost = post => post.availability
? post
: Object.assign({}, post, { text: "Goodbye" });
// ...
fetch("https://api.myjson.com")
.then(response => response.json())
.then(posts => posts.map(processPost))
This is easy to achieve with simple ternary statement.
return(
<div>
<div className="tiles">
{
orderedPosts.map(post => (
<div key={post.id}>
<div className="tile">
<p className="greeting">{post.availability ? post.text : 'Goodbye!'}</p>
</div>
</div>
))
}
</div>
</div>
);
Docs for ternary: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator
You can use ternary operator for displaying text.I hope it will helps you.
import React, { Component } from 'react';
import './styles.css'
class GetOnlinePosts extends Component {
constructor(props){
super(props);
this.state = {
error : null,
isLoaded : false,
posts : []
};
}
componentDidMount(){
fetch("https://api.myjson.com")
.then( response => response.json())
.then(
(result) => {
this.setState({
isLoaded : true,
posts : result
});
},
(error) => {
this.setState({
isLoaded: true,
error
})
},
)
}
render() {
const {error, isLoaded, posts} = this.state;
const orderedPosts = [...posts.filter((post) => post.availability), ...posts.filter((post) => !post.availability)]
if(error){
return <div>Error in loading</div>
}else if (!isLoaded) {
return <div>Loading ...</div>
}else{
return(
<div>
<div className="tiles">
{
orderedPosts.map(post => (
<div key={post.id}>
<div className="tile">
{
post.availability:( <p className="greeting">{post.text}</p>)?
(<p className="greeting">Goodbye</p>)
}
</div>
</div>
))
}
</div>
</div>
);
}
}
}
export default GetOnlinePosts;
Related
class Home extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoaded: false,
};
}
componentDidMount() {
fetch("https://reqres.in/api/users?page=2")
.then((res) => res.json())
.then((json) => {
this.setState({
isLoaded: true,
data: json,
});
});
}
render() {
var { isLoaded, data }= this.state;
if(!isLoaded){
return<div>Is isLoaded</div>
}
else{
return (
<div>
<ul>
{() =>
this.state.data.map((data, index) => (
<li key={index}>Email: {data.email}</li>
))
}
;
</ul>
</div>
);
}
}
}
export default Home;
Hii All , I know this question is asked many times but I cant figure it out I'am getting the error. I have checked for all the questions similar to this but haven't found specific solution if I use another link i.e, "https://jsonplaceholder.typicode.com/users" this one the code works fine .
The returned data from https://reqres.in/api/users?page=2 is not an array, but an object with a data property containing what you are looking for (an array). The result of the request is :
{"page":1,"per_page":6,"total":12,"total_pages":2,"data":[{"id":1,"email":"george.bluth#reqres.in","first_name":"George","last_name":"Bluth","avatar":"https://reqres.in/img/faces/1-image.jpg"},{"id":2,"email":"janet.weaver#reqres.in","first_name":"Janet","last_name":"Weaver","avatar":"https://reqres.in/img/faces/2-image.jpg"},{"id":3,"email":"emma.wong#reqres.in","first_name":"Emma","last_name":"Wong","avatar":"https://reqres.in/img/faces/3-image.jpg"},{"id":4,"email":"eve.holt#reqres.in","first_name":"Eve","last_name":"Holt","avatar":"https://reqres.in/img/faces/4-image.jpg"},{"id":5,"email":"charles.morris#reqres.in","first_name":"Charles","last_name":"Morris","avatar":"https://reqres.in/img/faces/5-image.jpg"},{"id":6,"email":"tracey.ramos#reqres.in","first_name":"Tracey","last_name":"Ramos","avatar":"https://reqres.in/img/faces/6-image.jpg"}],"support":{"url":"https://reqres.in/#support-heading","text":"To keep ReqRes free, contributions towards server costs are appreciated!"}}
So you cannot use map function, which is from the Array prototype, on the result of your request. You must access the data property first :
this.state.data.data.map((data, index) => ( // note the double data
<li key={index}>Email: {data.email}</li>
))
You could also assign json.data to the state.data to avoid the ugly .data.data :
this.setState({
isLoaded: true,
data: json.data, // note the .data
});
I think the problem is in brackets around your .map() method. Please try this
class Home extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoaded: false,
};
}
componentDidMount() {
fetch("https://reqres.in/api/users?page=2")
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
data: json,
});
});
}
render() {
const { isLoaded, data } = this.state;
if (!isLoaded) {
return <div>Is isLoaded</div>;
} else {
return (
<div>
<ul>
{data?.map((data, index) => {
return <li key={index}>Email: {data.email}</li>;
})}
</ul>
</div>
);
}
}
}
export default Home;
I don't see any error, it's working just fine.
Output:
Working Example: StackBlitz
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoaded: false,
};
}
componentDidMount() {
fetch('https://reqres.in/api/users?page=2')
.then((res) => res.json())
.then((json) => {
console.log(json.data);
this.setState({
isLoaded: true,
data: json.data,
email: null,
});
});
}
render() {
var { isLoaded, data } = this.state;
if (!isLoaded) {
return <div>Is isLoaded</div>;
} else {
return (
<div>
<div className="contents home">
<img
src="https://trucard.io/india/wp-content/uploads/2021/08/2021-June-TruCard-Logo.png
"
width={50}
alt="img"
className="trucard-img"
/>
</div>
<div className="button">
<button className="button-button">Load list</button>
</div>
<ul>
{this.state.data?.map((data, index) => (
<li key={index}>Email: {data.email}</li>
))}
;
</ul>
</div>
);
}
}
}
export default App;
I am building a Weather Application, and I need to seperate the Weather card into its own component. So far, while I had the Weather card in my Weather.js file it has been working good. But now I have seperated the Weather card into its own component but I cannot access the state.
This is my main component where I have my state:
export default class Weather extends React.Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
items: [],
selectedValue: ''
};
}
componentDidMount() {
fetch("http://api.weatherapi.com/v1/forecast.json?key=ca021cd2c43544e0be7112719202206&q=kosovo&days=3")
.then(res => res.json())
.then(
(result) => {
this.setState({
isLoaded: true,
items: result
});
},
(error) => {
this.setState({
isLoaded: true,
error
});
}
);
}
render() {
const { error, isLoaded, items } = this.state;
return (
<WeatherCard items={this.state}/>
)
}
}
This is the other component that I am trying to use the state
const WeatherCard = (props) => {
return (
<div>
<h2>Today</h2>
<span>{this.props.items.location.country}</span>
</div>
)
}
The error that I get is: undefined has no properties
render() {
const { error, isLoaded, items } = this.state;
return (
<WeatherCard items={items}/>
)
}
And in your weather component
const WeatherCard = (props) => {
return (
<div>
<h2>Today</h2>
<span>{props.items.location.country}</span>
</div>
)
render() {
const { error, isLoaded, items } = this.state;
return (
<WeatherCard items={this.state}/>
)
}
change to
render() {
const { error, isLoaded, items } = this.state;
return (
<WeatherCard items={items}/>
)
}
and
const WeatherCard = (props) => {
return (
<div>
<h2>Today</h2>
<span>{this.props.items.location.country}</span>
</div>
)
}
change to this
const WeatherCard = (props) => {
return (
<div>
<h2>Today</h2>
<span>{props.items.location.country}</span>
</div>
)
}
I have a JSON file:
[
{
"id": 1,
"availability": false
},
{
"id": 2,
"availability": true
}
]
What I would like to achieve is to automatically display an image of a tick if availability : true and to display an image of a cross if availability : false.
For example these are the names of the two images:
tick.jpg
cross.jpg
This is my code so far:
import React, { Component } from "react";
import "./styles.css";
class GetOnlinePosts extends Component {
constructor(props) {
super(props);
this.state = {
error: null,
isLoaded: false,
posts: []
};
}
componentDidMount() {
fetch("https://api.myjson.com")
.then(response => response.json())
.then(
result => {
this.setState({
isLoaded: true,
posts: result
});
},
error => {
this.setState({
isLoaded: true,
error
});
}
);
}
render() {
const { error, isLoaded, posts } = this.state;
const orderedPosts = [
...posts.filter(post => post.availability),
...posts.filter(post => !post.availability)
];
if (error) {
return <div>Error in loading</div>;
} else if (!isLoaded) {
return <div>Loading ...</div>;
} else {
return (
<div>
<div className="tiles">
{orderedPosts.map(post => (
<div key={post.id}>
<div className="tile"></div>
</div>
))}
</div>
</div>
);
}
}
}
export default GetOnlinePosts;
Unfortunately I am unable to have the images included in the with JSON. I would like the images to be within the <div className="tile"> </div> so any help on how to do this would be great. Thanks in advance.
<img src={post.availability ? 'tick.jpg' : 'cross.jpg'} />
I have a ReactJS webapp where I use webscokets to retrieve ticker prices from an API. When my webapp is standalone it works perfectly you can see in the image below.
But when I try to merge it in to my main react web app which has i18n localization no matter what I do I get this result. It seems it get stuck in the array or something. Maybe anyone has a clue how could I tackle this problem?
import React from 'react'
import axios from 'axios'
import { connect } from 'react-redux'
import Loading from '../elements/Loading'
import Ticker from './Ticker'
import TradeHistory from './TradeHistory'
import OrderBook from './OrderBook'
class Trade extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoaded: false
};
this.tradesCount = 20;
this.streams = ['#ticker','#depth20','#trade'];
}
_connectSocketStreams(streams) {
streams = streams.join('/');
let connection = btoa(streams);
this[connection] = new WebSocket(`wss://stream.binance.com:9443/stream?streams=${streams}`);
this[connection].onmessage = evt => {
let eventData = JSON.parse(evt.data);
if(eventData.stream.endsWith('#ticker')){
eventData.data.lastc = this.state.ticker ? this.state.ticker.c : 0
this.props.dispatch({
type: 'SET_TICKER',
data: eventData.data
})
this.setState({
loadedTicker: true
})
}
if(eventData.stream.endsWith('#trade')){
if(this.props.trades && Object.keys(this.props.trades).length > 0){
let trades = this.props.trades;
trades.push(eventData.data);
trades = trades.slice(-1*this.tradesCount);
this.props.dispatch({
type: 'SET_TRADES',
data: trades
})
this.setState({
loadedTrades: true
})
}
}
if(eventData.stream.endsWith('#depth20')){
this.props.dispatch({
type: 'SET_DEPTH',
data: eventData.data
})
this.setState({
loadedDepth: true
})
}
this.setState({
isLoaded: true
})
};
this[connection].onerror = evt => {
console.error(evt);
}
}
_disconnectSocketStreams(streams){
streams = streams.join('/');
let connection = btoa(streams);
if (this[connection].readyState === WebSocket.OPEN) {
this[connection].close();
}
}
componentDidMount() {
let symbol = this.props.match.params.symbol.toLowerCase();
this._connectSocketStreams(this.streams.map(i => `${symbol}${i}`));
axios({
method: 'get',
url: `https://cors-anywhere.herokuapp.com/https://www.binance.com/api/v1/aggTrades?limit=${this.tradesCount}&symbol=${this.props.match.params.symbol}`
})
.then(response => {
this.props.dispatch({
type: 'SET_TRADES',
data: response.data
})
this.setState({
isLoaded: true,
loadedTrades: true
})
})
.catch(error => {
this.setState({
isLoaded: false,
error: error
})
});
}
componentWillUnmount() {
let symbol = this.props.match.params.symbol.toLowerCase();
this._disconnectSocketStreams(this.streams.map(i => `${symbol}${i}`))
}
render() {
const { error, isLoaded, loadedDepth, loadedTicker, loadedTrades } = this.state;
if (error) {
return <div className="alert alert-danger">{error.message}</div>;
}
if (!isLoaded) {
return <Loading />;
}
return (
<React.Fragment>
<div className="row">
<div className="col-12">{loadedTicker ? <Ticker {...this.props.ticker} /> : <Loading />}</div>
</div>
<div className="row">
<div className="col-12 col-sm-6">{loadedTrades ? <TradeHistory trades={this.props.trades}/> : <Loading />}</div>
</div>
</React.Fragment>
)
}
}
export default connect(
state => state
)(Trade)
I am learning React and I am trying to use a component to show details of a selected item in a table, my problem is that when I click Next in the table (it is paginated), the state got updated and re-render the component and if I do click many times, it enqueue and the details component is changing between all the items I did click on.
I don't know if there is a good practice for doing this kind of things, i tried to search for something like this but nothing yet.
The component I am using (using public API):
import React from 'react';
class Pokemon extends React.Component {
constructor() {
super();
this.state = {
name: "",
abilities: [],
stats: [],
weight: 0,
height: 0,
base_experience: 0,
};
}
fetch_pokemon = () => {
fetch(this.props.pokemon_url)
.then(res => res.json())
.then(res => {
this.setState({
name: res.name,
abilities: res.abilities,
stats: res.stats,
weight: res.weight,
height: res.height,
base_experience: res.base_experience,
});
});
}
render() {
if(this.props.pokemon_url !== ''){
this.fetch_pokemon();
return (
<div>
<h1>{this.state.name}</h1>
Weight: {this.state.weight}<br />
Height: {this.state.height}<br />
Abilities:
<ul>
{this.state.abilities.map(({ability}, index) => {
return (<li key={index}>{ability.name}</li>);
})}
</ul>
</div>
);
}
else{
return (<h3>Choose one pokémon from the list...</h3>);
}
}
}
export default Pokemon;
My main component:
import React, { Component } from 'react';
//import logo from './logo.svg';
import './App.css';
import Pokemon from './Pokemon';
class App extends Component {
constructor() {
const i_pokemons = 25;
super();
this.state = {
pokemons: [],
pokemons_list: [],
pokemon_show_list: [],
p_init: 0,
p_final: i_pokemons,
pagination: i_pokemons,
pages: 0,
status: '',
enable_buttons: false,
current_page: 0,
current_pokemon_url: '',
URL: `https://pokeapi.co/api/v2/pokemon/?limit=99999`
};
}
componentDidMount(){
this.fetch_pokemons();
}
prev(){
this.setState({
current_page: this.state.current_page - 1,
p_init: this.state.p_init - this.state.pagination,
p_final: this.state.p_final - this.state.pagination
}, () => {
this.fetch_new_page();
});
}
next(){
this.setState({
current_page: this.state.current_page + 1,
p_init: this.state.p_init + this.state.pagination,
p_final: this.state.p_final + this.state.pagination
}, () => {
this.fetch_new_page();
});
}
fetch_new_page = () => {
const current_id = (this.state.current_page - 1) * this.state.pagination;
this.setState({
pokemon_show_list: this.state.pokemons_list.slice(current_id, current_id + 25)
});
this.fetch_pokemons();
}
fetch_pokemons = callback => {
this.setState({
status: 'Waiting for the server and retrieving data, please wait...',
enable_buttons: false
});
return new Promise((resolve, reject) => {
fetch(this.state.URL)
.then(res => res.json())
.then(res => {
if(!res.detail){
this.setState({
pokemons: res,
pokemons_list: res.results,
enable_buttons: true,
status: 'Done',
pokemon_show_list: res.results.slice(this.state.p_init, this.state.p_final)
});
if(this.state.pages === 0){
this.setState({
pages: Math.round(this.state.pokemons_list.length / this.state.pagination),
current_page: 1
});
}
resolve(true);
}else{
reject("Error");
this.setState({status: `Error`});
}
})
.catch(error => {
this.setState({status: `Error: ${error}`});
reject(error);
});
});
}
showPokemon({url}){
this.setState({
current_pokemon_url: url
});
}
render() {
console.log("Render");
return(
<div className="general">
<div className="pokemons-info">
{this.state.status !== '' && this.state.status}
<br />
<table className="pokemon-list">
<thead>
<tr>
<th>Name</th>
<th>More info.</th>
</tr>
</thead>
<tbody>
{this.state.pokemon_show_list.map((pokemon, index) => {
return (
<tr className="l" key={index}>
<td>{pokemon.name}</td>
<td><a className="btn btn-secondary" onClick={this.showPokemon.bind(this, pokemon)} href={`#${pokemon.name}`}>More info.</a></td>
</tr>
);
})}
</tbody>
</table>
<button className="btn btn-primary" disabled={this.state.current_page <= 1} onClick={this.prev.bind(this)}>Prev</button>
Page: {this.state.current_page} of {this.state.pages}
<button className="btn btn-primary" disabled={this.state.current_page === this.state.pages} onClick={this.next.bind(this)}>Next</button>
</div>
<Pokemon pokemon_url={this.state.current_pokemon_url}/>
</div>
);
}
}
export default App;
Feel free for giving any advice
I refactored and clean your code a little bit, but I guess the code below aims what you are looking for. (Read more about functional component 'logicless components').
const API = 'https://pokeapi.co/api/v2/pokemon/';
const PAGE_SIZE = 25;
function Status(props) {
return (
<div>{props.value}</div>
)
}
function Pagination(props) {
return (
<div>
<button
onClick={props.onPrevious}
disabled={props.disabled}>
Prev
</button>
<button
onClick={props.onNext}
disabled={props.disabled}>
Next
</button>
</div>
)
}
function Pokemon(props) {
return (
<div>
<h1>{props.pokemon.name}</h1>
Weight: {props.pokemon.weight}<br />
Height: {props.pokemon.height}<br />
Abilities:
<ul>
{props.pokemon.abilities.map(({ability}, index) => {
return (<li key={index}>{ability.name}</li>);
})}
</ul>
</div>
)
}
function PokemonTable (props) {
return (
<table className="pokemon-list">
<thead>
<tr>
<th>Name</th>
<th>More info.</th>
</tr>
</thead>
<tbody>
{props.children}
</tbody>
</table>
);
}
function PokemonRow (props) {
return (
<tr>
<td>{props.pokemon.name}</td>
<td>
<a href="#" onClick={() => props.onInfo(props.pokemon)}>
More info.
</a>
</td>
</tr>
);
}
class App extends React.Component {
state = {
pokemons: [],
detailedPokemons : {},
loading: false,
status : null,
previous : null,
next : null
}
componentDidMount () {
this.getPokemons(`${API}?limit=${PAGE_SIZE}`)
}
request(url) {
return fetch(url)
.then(blob => blob.json());
}
getPokemons (url) {
this.setState(state => ({
...state,
loading : true,
status : 'Fetching pokemons...'
}));
this.request(url)
.then(response => {
console.log(response)
this.setState(state => ({
...state,
previous : response.previous,
next : response.next,
pokemons : response.results,
loading : false,
status : null
}))
})
.catch(err => {
this.setState(state => ({
...state,
loading : false,
status : 'Unable to retrieved pockemons'
}));
});
}
getPokemonDetail (pokemon) {
const { detailedPokemons } = this.state;
const cachePokemon = detailedPokemons[pokemon.name];
if (cachePokemon !== undefined) { return; }
this.setState(state => ({
...state,
loading : true,
status : `Fetching ${pokemon.name} info`
}));
this.request(pokemon.url)
.then(response => {
this.setState(state => ({
...state,
loading: false,
status : null,
detailedPokemons : {
...state.detailedPokemons,
[response.name]: {
name: response.name,
abilities: response.abilities,
stats: response.stats,
weight: response.weight,
height: response.height,
base_experience: response.base_experience
}
}
}))
})
.catch(err => {
console.log(err)
this.setState(state => ({
...state,
loading : false,
status : 'Unable to retrieved pockemons'
}));
});
}
renderPokemons () {
const { pokemons } = this.state;
return pokemons.map(pokemon => (
<PokemonRow
pokemon={pokemon}
onInfo={this.handleView}
/>
));
}
renderDetailPokemons () {
const { detailedPokemons } = this.state;
return (
<ul>
{Object.keys(detailedPokemons).map(pokemonName => (
<li key={pokemonName}>
<Pokemon pokemon={detailedPokemons[pokemonName]}/>
</li>
))}
</ul>
)
}
handleView = (pokemon) => {
this.getPokemonDetail(pokemon);
}
handlePrevious = () => {
const { previous } = this.state;
this.getPokemons(previous);
}
handleNext = () => {
const { next } = this.state;
this.getPokemons(next);
}
render () {
const { loading, detailedPokemons, status, next, previous } = this.state;
return (
<div className='general'>
<div className="pokemons-info">
{ status && <Status value={status} /> }
<PokemonTable>
{this.renderPokemons()}
</PokemonTable>
<Pagination
disabled={loading}
onPrevious={this.handlePrevious}
onNext={this.handleNext}
/>
{
Object.keys(detailedPokemons).length > 0 &&
this.renderDetailPokemons()
}
</div>
</div>
)
}
}
ReactDOM.render(
<App />,
document.querySelector('#app')
);