How to print response Json data in jsx - reactjs

I want to render title and description in jsx (Reside in data-->feed->title or Description)
also want to render each title and each pub date (Reside in data->items[array]->title and pub date)
import React,{useState,useEffect} from 'react'
import axios from 'axios';
function Dashboard(){
const[posts,setPosts] = useState([])
useEffect(()=>{
axios.get('https://api.rss2json.com/v1/api.json?rss_url=http%3A%2F%2Frss.cnn.com%2Fservices%2Fpodcasting%2Fstudentnews%2Frss.xml')
.then(res=> {
console.log(res)
setPosts(res.data)
})
.catch(err=>{
console.log(err)
})
},[])
return(
<div className="App">
</div>
)
}

may be you are trying to do something like this ?
return(
<div className="App">
<div> {posts.feed && posts.feed.title} </div>
<div> {posts.feed && posts.feed.description} </div>
<div>
{posts.items && posts.items.map ( postItem => <div> {postItem.title} </div> ) }
</div>
</div>
)

So first of all I suggest you to make your screens class components, than you can make your child components as functional components like above. So you can make a async function that make a request and fetches the data to the state.
Why you getting cannot read property of "title"?
Becouse when you load your component It's instantly looking for your posts array. Which is empty at the begining It need some time to make request and fill your array with the recieved data, that's why you getting this error I believe.
So just try it like following
{posts.length && post.map .... .... ...

Try it like :
return(
<div className="App">
{
(posts.items!==undefined && posts.items.length>0) && posts.items.map ( ele=> {
return (<div>{ele.title} - {ele.pubDate} </div> )})
}
</div>
)

Related

Expression statement is not assignment or call when looping through a list and trying to create a grid layout of components

I am trying to create a grid layout of video components but my IDE gives me a warning saying
Expression statement is not assignment or call
import React, {Fragment} from 'react';
import VideoClip from "../Video/VideoClip";
function SubjectView(props) {
let ids = ["RfKHsvF69VdjdMu6bdugsyRcjYpQXrpKd6iZHeEknCkY00",
"RfKHsvF69VdjdMu6bdugsyRcjYpQXrpKd2ipHeEknCkY00",
"RfKHsvF69Vdjdiu6bdugsyRcjYpQXrpKd2iZHeEknCkY00"
];
return (
<Fragment>
<div className="columns-3" >
{ids.map((id)=>{
<VideoClip id={id}/>
console.log(id)
})}
</div>
</Fragment>
);
}
export default SubjectView;
I see the IDs printed in the console but nothing renders.
The video component looks like
function VideoClip() {
let { id } = useParams();
return (
<div className="container mx-auto px-4">
<MuxPlayer
streamType="on-demand"
playbackId={id}
metadata={{
video_id: "video-id-54321",
video_title: "Test video title",
viewer_user_id: "user-id-007",
}}
/>
</div>
);
}
export default VideoClip
I am wondering if I am trying to create the components incorrectly. Is there a best practice when trying to achieve this?
You're not returning any value from ids.map
<>
<div className="columns-3" >
{ids.map((id)=><VideoClip id={id}/>)}
</div>
</>
One issue is you are not returning <VideoClip id={id}/> in map function in jsx. Also, if map is used - key needs to be set
return (
<Fragment>
<div className="columns-3">
{ids.map((id) => {
console.log(id);
return <VideoClip key={id} id={id} />;
})}
</div>
</Fragment>
);
Next issue is about VideoClip component parameter. Id needs to be extracted in that way in case it is passed as an attribute. Also, memoize the objects that you are passing down to a components. Metadata here, for example.
function VideoClip({ id }) {
const metadata = useMemo(() => {
return {
video_id: "video-id-54321",
video_title: "Test video title",
viewer_user_id: "user-id-007"
};
}, []);
return (
<div className="container mx-auto px-4">
<MuxPlayer streamType="on-demand" playbackId={id} metadata={metadata} />
</div>
);
}
Last thing - wrap your array in useMemo so this array will not cause crazy rerenders.
const ids = useMemo(
() => [
"RfKHsvF69VdjdMu6bdugsyRcjYpQXrpKd6iZHeEknCkY00",
"RfKHsvF69VdjdMu6bdugsyRcjYpQXrpKd2ipHeEknCkY00",
"RfKHsvF69Vdjdiu6bdugsyRcjYpQXrpKd2iZHeEknCkY00"
],
[]
);
Note: you will see x2 logs in the console in the Codesandbox due to <StrictMode> is set.

Why does my app work when I comment and un-comment it

import React from 'react'
import CoinItem from './CoinItem'
const Coins = (props) => {
return (
<div className='container'>
<div>
<div className='heading'>
<p>#</p>
<p className='coin-name'>Coins</p>
<p>Price</p>
<p>24h</p>
<p className = 'hide-mobile'>Volume</p>
<p className = 'hide-mobile'>Market Cap</p>
</div>
{props.coins.map(coins => {
return (
<CoinItem coins={coins} key={coins.id} />
)
})}
</div>
</div>
)
}
export default Coins
With this code, my app won't render and I get the error, "Uncaught TypeError: props.coins.map is not a function." However, it directs me to the line where I create a div with the class name of the heading.
However, when I comment out:
{props.coins.map(coins => {
return (
<CoinItem coins={coins} key={coins.id} />
)
})}
and uncomment it again, my app renders perfectly with the API working, but once again, when I refresh, the app de-renders.
How do I fix this?
CodeSandbox link: https://codesandbox.io/s/busy-cloud-pcfne0?file=/src/components/Coins.js:409-512
A few things you can do is:
Ensure that the "coins" prop exists.
If it exists, make sure it is an Array and not an Object. You cannot use .map() on an Object. it is an Array method.
To avoid the code running a .map() when coins is null/undefined, add a ? after props.coins so that the .map() runs only if coins is defined.
{props.coins?.map(coin => { /*YOUR CODE HERE*/ })

UseEffect not rerendring page once products loaded in redux store

I am working on e-commerce project (MERN).So i got Molla e-commerce React template for better UX/UI.
In my root function am getting all products and store them using redux like this :
const updateStore = () => {
store.dispatch( getAllProducts() );
}
Everything was working fine until i found out that if i try to access product page for the first time (with empty localstorage as in incognito mode) i get nothing and the product object was undefined , if i refresh the page then it works fine.
The problem is when i try to access the products page with empty redux store , it doesn't wait or rerender when the data are stored.
I tryed to use useEffect() to wait for product change to rerender but it's not working .
This is my product page code :
function SingleProduct( props ) {
let productLink= props.match.params.link;
const {product} = props;
const [productLoaded,setProductLoaded] = useState(false);
useEffect( () => {
if(productLoaded){
productGallery();
document.querySelector( '.skel-pro-single' ).classList.remove( 'loaded' );
let imgLoad = imagesLoaded( ".product-main-image", { background: true } );
imgLoad.on( 'done', function ( instance, image ) {
document.querySelector( '.skel-pro-single' ).classList.add( 'loaded' );
} );
}
}, [ productLink ] )
useEffect(()=>{
if(product){
setProductLoaded(true);
}
},[product])
return (
productLoaded ?
<>
<Helmet>
<title></title>
</Helmet>
<h1 className="d-none"></h1>
<div className="main">
<div className="page-content">
<div className="container">
<div className="product-details-top skeleton-body">
<div className="row skel-pro-single">
<div className="col-md-6">
<div className="skel-product-gallery">
</div>
<MediaOne link={ productLink } />
</div>
<div className="col-md-6">
<div className="entry-summary row">
<div className="col-md-12">
<div className="entry-summary1"></div>
</div>
<div className="col-md-12">
<div className="entry-summary2"></div>
</div>
</div>
<ProductDetailOne link={ productLink } />
</div>
</div>
</div>
<DescOne link={ productLink } />
<h2 className="title text-center mb-4">You May Also Like</h2>
<RelatedProducts />
</div>
</div>
<StickyBar link={ productLink } />
<QuickView />
</div>
</>
:
<></>
)
}
function mapStateToProps( state, props ) {
return {
product: state.data.products.filter( product => product.link == props.link )[ 0 ]
}
}
export default connect(mapStateToProps)(SingleProduct);
I tried to wait for product change using the useEffect and productLoaded state since it's undefined on first page render but it still showing undefined.
'product' variable, I think, is an object, be aware about what could happen if you use useEffect with that.
const a = {a:123};
const b = {a:123};
(a === b) === false
if it is possible see if the id or a string/number changes
The first useEffect will run before the second one so when this will run it will have productLoaded on false.
Try to gain productLoaded from props (you will not have to manage the asyncronicity of useEffect).
assuming that product is undefined before loading
const productLoaded = !!product;
useEffect( () => {
if(productLoaded){
..."do here what you need"
}
}, [ productLink, productLoaded ] )
maybe you can achieve a change in the css classes
<div className={`row skel-pro-single ${productLoaded?"loaded":""}`}>
as a suggestion try to use react as a templating with variables in the returning jsx, please don't mix js dom interaction and react interactions, they could disturb each other (react will try to report the part of the dom that he manages to the state he calculated, so could overwrite your changes made by
document.querySelector( '.skel-pro-single' ).classList.remove

Create a custom Hook for splitting strings (React JS)

I'm working with React JS (hooks) for recently. For a project, I need to split many strings in different divs. So, I created a function to this, that saves me some time! My actual question is : Should I create a custom Hook instead of my function ?
Of course, the actual code works, but as a beginner, I don't know if my way is clean. I need feedbacks cause my main goal to write the best and clear code as possible.
// Splitting Texts
const splitText = str => {
return (
<div>
{str.split(' ').map((item, index) => {
return (
<div key={index}>
{item}
</div>
);
})}
</div>
);
};
// Main App
export default function App() {
const name = splitText('Lucie Bachman');
const description = splitText('Hey, this is my first post on StackOverflow!');
return (
<div className="App">
<h1>{name}</h1>
<h2>{description}</h2>
</div>
);
}
Expected results :
<h1>
<div>
<div>Lucie</div>
<div>Bachman</div>
</div>
</h1>
I'm super excited to have joined the community!
Thanks to you, and take care.
Lucie Bachman
A custom hook is something that uses out of the box react hooks to actually provide a logic and return data.
If the function returns JSX, its actually just a function or can be used as a functional component
Since you only want to split string once you can convert it into a component and use React.memo to optimize rendering
// Splitting Texts
const SplitText = React.memo(({str}) => {
return (
<div>
{str.split(' ').map((item, index) => {
return (
<div key={index}>
{item}
</div>
);
})}
</div>
);
});
// Main App
export default function App() {
return (
<div className="App">
<h1><SplitText str={'Lucie Bachman'} /></h1>
<h2><SplitText str={'Hey, this is my first post on StackOverflow!''} /></h2>
</div>
);
}

how to go about with this Short circuit evaluation?

I want to add PictureAlbums along with iframe. Basically, I'm trying to write like this: if timerStates is complete then render <iframe> and also PictureAlbum component.
With the code below I'm able to render only <PictureAlbums /> and not iframe. How do I solve this?
import React from 'react';
import PictureAlbums from './PictureAlbums';
import * as timerStates from './TimerState';
const lp = (val) => {
if (val < 10) return `0${val}`;
return `${val}`;
}
const TimerDisplay = (props) => (
<div>
<div>
{
(props.timerState === timerStates.COMPLETE)
&& <iframe src="https://www.youtube.com/"></iframe>
&& <PictureAlbums />
}
</div>
<div>
<h2>{`${lp(props.currentTime.get('hours'))}:${lp(props.currentTime.get('minutes'))}:${lp(props.currentTime.get('seconds'))}`}</h2>
</div>
</div>
);
You can use a React.Fragment for that to give both elements a common parent without inserting an extra element in the DOM.
{props.timerState === timerStates.COMPLETE && (
<React.Fragment>
<iframe src="https://www.youtube.com/"></iframe>
<PictureAlbums />
</React.Fragment>
)}

Resources