How to fetch Multiple news data using RSS Feed in React JS - reactjs

I already done RSS Feed implementation. Now I'm able to fetch 1 News using this code. I want to fetch multiple news using this code. How can I do that.
Thank in advances.
class FetchDataFromRSSFeed extends Component {
constructor() {
super();
this.state = {
recentBlogPost: {
name: '',
url: ''
}
}
}
FetchDataFromRssFeed() {
var request = new XMLHttpRequest();
request.onreadystatechange = () => {
if (request.readyState == 4 && request.status == 200) {
var myObj = JSON.parse(request.responseText);
for (var i = 0; i < 1; i ++) {
this.setState({
recentBlogPost: {
name: myObj.items[i].title,
url: myObj.items[i].link
}
});
}
}
}
request.open("GET", "https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fblog.codecarrot.net%2Ffeed.xml&order_dir=desc&count=30", true);
request.send();
}
componentDidMount() {
{this.FetchDataFromRssFeed()}
}
render() {
return (
<div>
Check out our blog: <a target="_blank" href={this.state.recentBlogPost.url}>{this.state.recentBlogPost.name}</a>
</div>
);
}
}

I already done RSS Feed implementation. Now i'm able to fetch 1 News using this code. I want to fetch multiple news using this code.
Instead of defining object like this,
recentBlogPost: {
name: '',
url: ''
}
you need to define an array,
recentBlogPost: []
Now instead of setting first record only,
var myObj = JSON.parse(request.responseText);
for (var i = 0; i < 1; i ++) {
this.setState({
recentBlogPost: {
name: myObj.items[i].title,
url: myObj.items[i].link
}
});
}
You need to set complete array,
var myObj = JSON.parse(request.responseText);
this.setState({
recentBlogPost: myObj.item
});
And finally displaying only 1 record as,
<div>
Check out our blog: <a target="_blank" href={this.state.recentBlogPost.url}>{this.state.recentBlogPost.name}</a>
</div>
You need to iterate over the state array,
{this.state.recentBlogPost.map(post=>{
return <div key={post.title}>Check out our blog: <a target="_blank" href={post.link}>{post.title}</a></div>
})}

Adding to the great explanation by #ravibagul91, here's the complete React component. Details on the strategy can be found in:
Array.prototype.map()
How to Use Async/Await in React
Lists and Keys
import React, { Component } from "react";
export default class FetchDataFromRSSFeed extends Component {
constructor() {
super();
this.state = {
items: []
};
}
async componentDidMount() {
try {
const response = await fetch(
"https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fblog.codecarrot.net%2Ffeed.xml&order_dir=desc"
);
const json = await response.json();
this.setState({ items: json.items });
} catch (error) {
console.log(error);
}
}
render() {
console.log(this.state);
return (
<div>
Check out our blog:
{this.state.items.map(item => (
<li key={item.guid}>
<a target="_blank" rel="noopener noreferrer" href={item.link}>
{item.title}
</a>
</li>
))}
</div>
);
}
}
The unstyled results look like this:

Related

class not applying to all html elements in reactjs after adding new data

import React from 'react';
import { CodeGenerator } from '#babel/generator';
class Test extends React.Component {
constructor(props){
super(props);
this.state = {
data:[{"type": "Beverages", "sub_types": ["Water", "Coffee"]}]
}
}
componentDidMount(){
let toggler = document.getElementsByClassName("caret");
for (let i = 0; i < toggler.length; i++) {
toggler[i].addEventListener("click", function() {
this.parentElement.querySelector(".nested").classList.toggle("active");
this.classList.toggle("caret-down");
});
}
}
callAgain = () => {
let toggler = document.getElementsByClassName("caret");
for (let i = 0; i < toggler.length; i++) {
toggler[i].addEventListener("click", function() {
this.parentElement.querySelector(".nested").classList.toggle("active");
this.classList.toggle("caret-down");
});
}
}
appendSecond = () => {
this.setState(previousState => ({
data: [...previousState.data, {"type": "Beveragee2", "sub_types": ["Water", "Coffee"]}]
}), () => this.callAgain());
}
render(){
return (
<div style={{ margin:'1cm' }}>
<ul id="myUL">
{
this.state.data.map((d, index) => (
<li><span class="caret">{d.type}</span>
<ul class="nested">
{
d.sub_types.map(sub => (
<li>{sub}</li>
))
}
</ul>
</li>
))
}
</ul>
<button type="button" onClick={this.appendSecond}>button</button>
</div>
)
}
}
export default Test;
Hi, here i have shared my Code.
I am just created one tree view using html/css and it is working firsttime when i am clicking the caret icon and it toggles.
But when i am appending one more tree on to my data it is not working the previous tree but, working the last inserted tree.
Please run this code for better understanding. I tried to explain but, not sure you guys got or not what i am trying to say.
Please have a look.
There are quite a number of things wrong about your approach to everything.
When using React you shouldn't touch the DOM directly, It is the job of React to manipulate the DOM while you just set the conditions in which it should update.
example code below is wrong in react and none of it is necessary:
componentDidMount(){
let toggler = document.getElementsByClassName("caret");
for (let i = 0; i < toggler.length; i++) {
toggler[i].addEventListener("click", function() {
this.parentElement.querySelector(".nested").classList.toggle("active");
this.classList.toggle("caret-down");
});
}
}
Instead of the above code, you can simply set the state data and reference the state in your render(). You should read more about how React works from the official docs or other resources.
You can declare your menu items in the state like below:
this.state = {
menuItems: [
{
order: 0,
title: 'beverages',
submenu: [{
title: 'water',
sub: []
},
{
title: 'Coffee',
sub: []
}],
isActive: false
},
{
order: 1,
title: 'cereal',
submenu: [],
isActive: false
}
]
}
Then map over the menuItems state in your render. You will then add conditions based on isActive state.
You would also need a toggle function to set the isActive state to true or false.
Instead of class="caret" use className="caret" React reserves the name class for class components.
I hope you get the idea.
import React from 'react';
class Test extends React.Component {
constructor(props){
super(props);
this.state = {
data:[{"type": "Beverages", "sub_types": ["Water", "Coffee"]}],
actives: []
}
}
appendSecond = () => {
this.setState(previousState => ({
data: [...previousState.data, {"type": "Beveragee"+Math.floor((Math.random() * 100) + 1), "sub_types": ["Water", "Coffee"]}]
}));
}
handleToggle = (name) => {
let actives = this.state.actives
if(actives.includes(name)){
for(let i=0; i<actives.length; i++){
if(actives[i] === name){
actives.splice(i, 1)
}
}
this.setState({
actives: actives
})
return
}
this.setState({
actives:[...this.state.actives, name]
});
}
render(){
return (
<div style={{ margin:'1cm' }}>
<ul id="myUL">
{
this.state.data.map((d, index) => (
<li><span class="caret" onClick={() => this.handleToggle(d.type)}>{d.type}</span>
<ul class={this.state.actives.includes(d.type) ? "nested active" : "nested"}>
{
d.sub_types.map(sub => (
<li>{sub}</li>
))
}
</ul>
</li>
))
}
</ul>
<button type="button" onClick={this.appendSecond}>button</button>
</div>
)
}
}
export default Test;

Display one object from fetched data undefined

I'm new to React and I'm having a hard time trying to display the first element of an array for example. I'm getting a TypeError: Cannot read property 'title' of undefined even if it's working with a console.log. Here is the code :
constructor() {
super()
this.state = {
posts: []
}
this.componentDidMount = this.componentDidMount.bind(this)
}
async componentDidMount() {
const url = "https://jsonplaceholder.typicode.com/posts";
const response = await fetch(url);
const data = await response.json();
this.setState({
posts: data
})
console.log(data); //working
console.log(this.state.posts) //working
console.log(this.state.posts[0].title) //working
}
render() {
return (
<div className="head-title"> { this.state.posts[0].title } </div>
<div className="head-body"> { this.state.posts[0].body} </div>
)
}
What am I doing wrong ?
You can do like this. In addition to my answer :
class test extends Component{
constructor() {
super()
this.state = {
posts: [],
loading :true
}
this.componentDidMount = this.componentDidMount.bind(this)
}
async componentDidMount() {
const url = "https://jsonplaceholder.typicode.com/posts";
const response = await fetch(url);
const data = await response.json();
this.setState({
posts: data,
loading:false
})
console.log(data); //working
console.log(this.state.posts) //working
console.log(this.state.posts[0].title) //working
}
}
render() {
if(this.state.loading) return null;//Dont render component
//or add ternary condition
return (
<div className="head-title"> { this.state.posts[0].title } </div>
<div className="head-body"> { this.state.posts[0].body} </div>
)
}
}
Your component will attempt to render this.state.posts[0].title while the request still hasn't finished and thus will throw an error.
Add a check to make sure your data exists for example like so:
render() {
return (
<div className="head-title"> { (this.state.posts.length > 0) ? this.state.posts[0].title : null } </div>
<div className="head-body"> { (this.state.posts.length > 0) ? this.state.posts[0].body : null} </div>
)
}

Why I can not receive results of axios in ReactJs Datatables in render section

Good Day, I can receive the results of my simple object state variable "var blogs" in My datatables plugin in render section of my component, But if I try to change the variable in datatable in render section to variable that I get from axios "var blogs_ajax" I can not see the results of datatable action on my screen
That is my code, Please help me Sorry I can not put this code in action snippet because of including Datatables library
export default class AllBlogs extends Component {
constructor() {
super();
this.state = {
blogs: [
{
"title":"функция Query — подробное руководство",
"author":1,
"viewers":213
},
{
"title":"функция Query — подробное руководство",
"author":1,
"viewers":213
}
],
blogs_ajax:[]
};
this.navItems();
}
componentDidMount() {
}
async navItems() {
await axios
.post("http://localhost:8000/api/blogs/getAllBlogs/")
.then(response => {
//console.log(response);
return response;
}
)
.then(json => {
console.log(json.data.data)
if (json.data.success) {
this.setState(() => ({blogs_ajax: json.data.data.aaData}))
} else alert("Blogs Failed!");
})
.catch(error => {
alert(`An Error Occured! ${error}`);
});
}
render() {
const {blogs_ajax} = this.state;
console.log(this.state.blogs_ajax) // But I can see the result here
return (
<div id="content" className="animated fadeInUp">
<WidgetGrid>
<div className="row">
<article className="col-sm-12">
<JarvisWidget id="wid-id-0" editbutton={false} color="darken">
<header>
<span className="widget-icon">
<i className="fa fa-table"/>
</span>
<h2></h2>
</header>
<div>
<div className="widget-body no-padding">
<Datatable
options={{
data: this.state.blogs_ajax ,
// But I can not receive array of objects here from axios
columns: [
{data: "title"},
{data: "author"},
{data: "viewers"},
]
}}
Your render section is going first and you didnt get your axios result.Try to go this way check if results already presents
${this.state.postBlog.status ?
<Datatable
options={{
columns: [
{data: "title"},
{data: "author"},
{data: "viewers"},
]
}}
paginationLength={true}
className="table table-striped table-bordered table-hover"
width="100%"
>
Your state contains two properties, blogs and blogs_ajax.
In your render method, you create a const from the state, but this contains two objects, not the array of objects.
To me it looks like you have a small hard-coded list whilst getting your table working, but now it is you want to display the array in this.state.blogs_ajax.
Change the constant to this.state.blogs_ajax, or even better delete the constant and in the data tables Options object, just assign this.state.blogs_ajax. For clarity, datatables is expecting an array of objects, not an object.
OK, this issue was not how you're passing in the data now. It is more to do with how you're handling the data updates in your datatables.net wrapper.
I've used datatables quite a bit in Javascript and within React, but I've never seen the table instatiated in that way.
When the data does finally load, you need to check when or not to update the component. Saying true in shouldComponentUpdate usually does the trick, but not in the way you create the table.
I've two examples below.
Play.js
import Datatable from '../components/datatable';
import React from "react";
export default class AllBlogs extends React.Component {
constructor() {
super();
this.state = {
blogs: [
{
"title":"функция Query — подробное руководство",
"author":1,
"viewers":213
},
{
"title":"функция Query — подробное руководство",
"author":1,
"viewers":213
}
],
blogs_ajax:[]
};
}
componentDidMount() {
this.navItems();
}
async navItems() {
//CHA - simulating a small gap in between the table initially loading and the data arriving.
this.setState({blogs_ajax: this.state.blogs_ajax});
}
render() {
console.log(this.state.blogs) // But I can see the result here
return (
<div id="content">
<h1>React Table</h1>
<Datatable
options={{ data: this.state.blogs,
columns: [
{data: "title"},
{data: "author"},
{data: "viewers"},
]
}} />
</div>
);
}
}
Next is trimmed down example of your datatables wrapper from your repo. look at the comments prefixed CHA.
import React from "react";
import $ from "jquery";
require("datatables.net-bs");
require("datatables.net-buttons-bs");
require("datatables.net-buttons/js/buttons.colVis.js");
require("datatables.net-buttons/js/buttons.flash.js");
require("datatables.net-buttons/js/buttons.html5.js");
require("datatables.net-buttons/js/buttons.print.js");
require("datatables.net-colreorder-bs");
require("datatables.net-responsive-bs");
require("datatables.net-select-bs");
export default class Datatable extends React.Component {
componentDidMount() {
this.datatable(this.props.data);
console.log("CHA - In datables.js did mount - data will be undefined initially");
console.log(this.props.data);
}
shouldComponentUpdate(nextProps, nextState){
console.log("CHA - shouldcomponentupdate - we should now have data.");
console.log(nextProps.options.data);
console.log("CHA - because of the way you build the datatable, we need to rebuild instead of redraw.");
this.datatable(nextProps.options.data);
return true;
}
datatable() {
const element = $(this.refs.table);
let { options } = { ...this.props } || {};
let toolbar = "";
if (options.buttons) toolbar += "B";
if (this.props.paginationLength) toolbar += "l";
if (this.props.columnsHide) toolbar += "C";
if (typeof options.ajax === "string") {
let url = options.ajax;
options.ajax = {
url: url,
complete: function(xhr) {
// AjaxActions.contentLoaded(xhr)
}
};
}
options = {
...options,
...{
dom:
"<'dt-toolbar'<'col-xs-12 col-sm-6'f><'col-sm-6 col-xs-12 hidden-xs text-right'" +
toolbar +
">r>" +
"t" +
"<'dt-toolbar-footer'<'col-sm-6 col-xs-12 hidden-xs'i><'col-xs-12 col-sm-6'p>>",
oLanguage: {
sSearch:
"<span class='input-group-addon input-sm'><i class='glyphicon glyphicon-search'></i></span> ",
sLengthMenu: "_MENU_"
},
autoWidth: false,
retrieve: true,
responsive: true
}
};
console.log("before const call");
console.log(options);
const _dataTable = element.DataTable(options);
if (this.props.filter) {
// Apply the filter
element.on("keyup change", "thead th input[type=text]", function() {
_dataTable
.column(
$(this)
.parent()
.index() + ":visible"
)
.search(this.value)
.draw();
});
}
if (!toolbar) {
element
.parent()
.find(".dt-toolbar")
.append(
'<div class="text-right"><img src="assets/img/logo.png" alt="SmartAdmin" style="width: 111px; margin-top: 3px; margin-right: 10px;"></div>'
);
}
if (this.props.detailsFormat) {
const format = this.props.detailsFormat;
element.on("click", "td.details-control", function() {
const tr = $(this).closest("tr");
const row = _dataTable.row(tr);
if (row.child.isShown()) {
row.child.hide();
tr.removeClass("shown");
} else {
row.child(format(row.data())).show();
tr.addClass("shown");
}
});
}
}
render() {
let {
children,
options,
detailsFormat,
paginationLength,
...props
} = this.props;
console.log("CHA - In render");
console.log(this.props);
return (
<table {...props} ref="table">
{children}
</table>
);
}
}

Render a simple list in React with promises

I'm trying to render some content from a service which returns a promise, but I can't figure out how I should return the data in my "return" block.
It's no problem to return some static data, as shown in this example. But how can I return the data from the commented code in the same way?
The image shows the console, where you can see the promise.
I know the answer is probaly very simple, but I just can't wrap my head around it.
render() {
const data2 = [
{title:'item one', id:'000'},
{title:'item two', id:'001'}
];
console.log(data2);
const data = firebaseCon.content.get('text', { fields: ['id', 'title'] });
console.log(data);
var itemList = data2.map(function(item) {
return <li className="item" key={item.id}>{item.title}</li>;
});
return (
<ul>
{itemList}
</ul>
)
}
First of all, I would say that you are doing in wrong way.
You should never make a server request in render function.
You should make a server request in componentWillMount() or componentDidMount().
If you know async/await concept then it would be helpful for you.
You can check this link..
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
You can try like this one...
import React, { Component } from 'react';
export default class ListData extends Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
async componentDidMount() {
const data = await firebaseCon.content.get('text', { fields: ['id', 'title'] });
this.setState({ data });
}
render() {
const { data } = this.state;
const itemList = data.map(function(item) {
return <li className="item" key={item.id}>{item.title}</li>;
});
return (
<div>
{data.length > 0 &&
<ul>
{ itemList }
</ul>
}
</div>
);
}
}
Hope it will be help
This code will handle the object that is returned by api and also moves the fetching to componentDidMount.
constructor(props) {
super(props);
this.state = {
data: [],
}
}
componentDidMount() {
firebaseCon.content.get('text', { fields: ['id', 'title'] })
.then((response) => {
let data = [];
for (item in response) {
data.push(response[item]);
}
this.setState({ data });
});
}
render() {
let itemList = this.state.data.map(function(item) {
return <li className="item" key={item.id}>{item.title}</li>;
});
return (
<ul>
{itemList}
</ul>
)
}
A closer look at Promises' methods then and catch should make it clearer: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
Have you seen this?
https://github.com/axios/axios
Promise based HTTP client for the browser and node.js.
You can see it in action in this tutorial, used with React:
https://codeburst.io/building-appointment-scheduler-app-in-react-and-nodejs-f163c4eaab6b
Hope it helps.

react getting observable values in component

Seting the obsrv array in the component below;
class AnnouncementState {
#observable categories =[];
constructor(){
this.getAnnouncementCategory();
}
getAnnouncementCategory() {
fetch(`..`)
.then((response) => {
return response.json();
})
.then((response) => {
this.categories = response.value.map((item , i)=>{ return {Id:item.Id, Title:item.Title} });
}, (error) => {
});
}
}
I checked the retrieved values its ok. and I try set it in component and render it below;
#observer
class AnnouncementComponent extends React.Component {
categories = [];
componentWillMount(){
debugger
this.categories=this.props.announcement.categories;
}
render() {
const listItems = this.categories.map((item) => {
return (<li>...</li>)
});
return (
<div id="announcements-tab">
List Items:
<ul className="nav nav-tabs">
{listItems}
</ul>
</div>
);
}
}
I expected to see all list items but none(only "listItems" string)in html, no error in console. how can I fix and debug it ? using "debugger" keyword shows nothing for observable.
In your code, I don't see where are you creating the instance of AnnouncementState. Here an example how can you get the categories list.
e.g.
class AnnouncementState {
#observable categories =[];
#action getAnnouncementCategory() {
fetch(`..`)
.then((response) => {
return response.json();
})
.then((response) => {
this.categories = response.value.map((item , i)=>{ return {Id:item.Id, Title:item.Title} });
}, (error) => {
});
}
}
export default new AnnouncementState(); //here you can create the instance.
#observer
#inject('store') //here substitute with your store name, the name you set in your provider
class AnnouncementComponent extends React.Component {
componentWillMount(){
debugger
this.props.store.getAnnouncementCategory();
}
render() {
const listItems = this.props.store.categories.map((item) => {
return (<li>...</li>)
});
return (
<div id="announcements-tab">
List Items:
<ul className="nav nav-tabs">
{listItems}
</ul>
</div>
);
}
}
This should work, just be sure you pass the correct store with <Provider store={store}>.

Resources