I am making a react app which fetches and displays some CSV file data from the public folder. My react container looks like this:
import React, { Component } from 'react'
import * as Chart from "chart.js";
import { connect } from 'react-redux'
import { Bar } from 'react-chartjs-2'
import * as actions from "../actions"
import * as Papa from 'papaparse'
function mapStateToProps({stats}) {
return {
data: stats.data
}
}
class Stats extends Component {
fetchCsv(fileName) {
return fetch(fileName).then(function (response) {
let reader = response.body.getReader();
let decoder = new TextDecoder('utf-8');
return reader.read().then(function (result) {
return decoder.decode(result.value);
});
});
}
constructor(props){
super(props);
}
async componentDidMount() {
let PlayerArray = [], BallByBallArray = [], MatchArray = [],
PlayerMatchArray = [], SeasonArray = [], TeamArray = [];
let PlayerMatchData = await this.fetchCsv("Player_Match.csv");
Papa.parse(PlayerMatchData, {
complete: function(results) {
console.log("Finished:", results.data);
PlayerMatchArray = results.data;
console.log("entries.length: " + results.data.length);
}
});
}
render() {
return (
<div>
</div>
)
}
}
export default connect(
mapStateToProps, actions
)(Stats)
This is fetching the content of Player_Match.csv file using the fetchCsv function asynchronously and storing it in PlayerMatchData variable.
Then PlayerMatchData is being parsed by papaparse. The issue is that the file has 12700 entries in it and it is only fetching 3776 entries in google chrome.
Also, strangely it is fetching 1660 entries in firefox
Any input will be appreciated. :)
Edit: Link to the data: https://www.kaggle.com/harsha547/indian-premier-league-csv-dataset#Player_Match.csv
Okay, so I got the answer. As told by #SergiuParaschiv reader.read() only reads one chunk of data. So I instead used the fetch function to complete the task. There was no issue in the parsing.
await fetch("Player_Match.csv")
.then(response => response.text())
.then(text => {
PlayerMatchData = text;
// console.log(text)
})
This will do the task.
Related
I am trying to make a simple React Native app. For the start there is one default language, there is a button, by clicking on it changing the language and reloads the app with the new language. The idea is to store that language in the AsyncStorage (#react-native-async-storage/async-storage).
Here is my cache.js:
import AsyncStorage from '#react-native-async-storage/async-storage';
import moment from 'moment';
const prefix = 'cache';
const expiryInMinutes = 5;
const store = async (key, value) => {
try {
const item = {
value,
timestamp: Date.now()
}
await AsyncStorage.setItem(prefix + key, JSON.stringify(item));
} catch (error) {
// console.log(error);
}
}
const get = async (key) => {
try {
const value = await AsyncStorage.getItem(prefix + key);
const item = JSON.parse(value);
if(!item) return null;
if(isExpired(item)) {
await AsyncStorage.removeItem(prefix + key);
return null;
}
return item.value;
} catch(error) {
// console.log(error);
}
}
const isExpired = (item) => {
const now = moment(Date.now());
const storedTime = item.timestamp;
return now.diff(storedTime, 'minutes') > expiryInMinutes;
}
export default { store, get };
and here is my App.js:
import React from 'react';
import { Button, StyleSheet, Text, View } from 'react-native';
import * as Updates from 'expo-updates';
import i18n from './app/locales/locales';
import cache from './app/utility/cache';
export default function App() {
// When a value is missing from a language it'll fallback to another language with the key present.
i18n.fallbacks = true;
i18n.locale = 'de';
cache.get('lang').then(function(result) {
if(result) {
i18n.locale = result;
// console.log("New lang " + result);
}
});
const handleRestart = async () => {
// console.log("Storing lang: ");
// console.log("Reseting lang: ");
cache.store("lang", 'en');
// console.log(cache.get('lang'));
// console.log("Hmm");
// console.log(i18n.locale);
await Updates.reloadAsync();
}
return (
<View style={styles.container}>
<Text>{i18n.t('hello')}</Text>
<Button title="Restart" onPress={handleRestart} />
</View>
);
}
It starts in German, when I press the button it stores the English, but it doesn't change the application language. What am I doing wrong?
I'm think UI is not getting updated, because react re-renders only if props or state gets changed. Since non of those changed, you are not going to see any updated on UI.
try something like this
const [lang, setLang] = React.useState(langValueFromStorage);
const handleRestart = () => {
cache.get('lang').then(function(result) {
if(result) {
i18n.locale = result;
setLang(result)
}
});
}
I have found a solution though it looks a bit hacky. i18n.js:
import AsyncStorage from '#react-native-async-storage/async-storage';
import i18n from 'i18next';
import {initReactI18next} from 'react-i18next';
import en from './src/localization/en/en.json';
import uz from './src/localization/uz/uz.json';
const resources = {
en: {
translation: en,
},
uz: {
translation: uz,
},
};
const getDefaultLang = async () => {
const storedLang = await AsyncStorage.getItem('lang');
return i18n
.use(initReactI18next)
.init({
resources,
lng: storedLang ? storedLang : 'uz',
interpolation: {
escapeValue: false,
},
fallbackLng: ['uz', 'en'],
});
};
export default getDefaultLang();
There is also a plugin used for detecting lang from asyncstorage which I have just found
I'm working on a react project where I have created an API and that I want to use for my react project, I'm dealing with react hooks and not able to call API correctly. I have tried couple of things, but I keep getting one or other kind of error.
Latest method I have tried is giving me this error
Line 8:20: React Hook "useFetch" is called in function "filterList" which is neither a React function component or a custom React Hook function
Code for filterList.js look like this
/* to filter the products based on the categories */
import useFetch from './apiService'
export default function filterList(arr, method, courses) {
const URL = "http://localhost:8000/api/getCourses";
const result = useFetch(URL, {});
courses = result;
console.log(courses, 'Inside filterList')
if(method == null) return courses;
else {
return courses.filter(course => {
const categoryArray = course.category.split(" ");
if(arr.length > 0) {
if(categoryArray.some(r => arr.indexOf(r) >= 0)) {
return course;
}
}
else {
return courses;
}
return courses;
})
}
}
and code for apiService.js where I have created useFetch function look like this
import { useEffect, useState } from 'react';
// to fetch the data from api
const useFetch = (url, defaultData) => {
const [data, updateData] = useState(defaultData);
useEffect(() => {
async function fetchData() {
const response = await fetch(url);
const json = await response.json();
updateData(json);
}
fetchData();
}, [url]);
return data;
};
export default useFetch;
Please let me know what is the thing that I'm doing wrong and what should be correct method to do this.
I'm use AsyncStorage, but I think I do not use correcly...
file functions.js
import { AsyncStorage } from 'react-native';
const Functions = {
async storeItem(key, item) {
try {
AsyncStorage.setItem()
var jsonOfItem = await AsyncStorage.setItem(key, JSON.stringify(item));
return jsonOfItem;
} catch (error) {
console.warn(error.message);
}
},
async retrieveItem(key) {
try {
const retrievedItem = await AsyncStorage.getItem(key);
const item = JSON.parse(retrievedItem);
return item;
} catch (error) {
console.warn(error.message);
}
}
}
export default Functions;
File home.js
import Functions from 'Constants/functions';
export default class Home extends Component {
constructor(props) {
super(props);
product = Functions.retrieveItem('products');
console.warn(product);
}
}
console.warn(product) returned
{"_40":0,_65":1,"_55":null,"_72":null}
I believe that this happens because I receive the object before it has been processed. Because if I put a console.warn before the return of the retrieveItem function it shows the object well...
is a Promise so... you need to use
Functions.retrieveItem('products').then((res) => { //do something with res });
For some reason my map function is not returning anything in the render.
Basically I have a function that does a scrape with cheerio and then it stores the results in an array, then sets the state with it. When I check the react tools it shows that the state is updated with the array as expected. However, when the map function does not render anything and is blank on the screen.
I used very similar code in my last project but it's not working here, I feel I'm missing something simple but can't figure it out.
Here's the code:
import React, { Component } from 'react';
import { Trender } from '../Trender/trender';
import request from 'request';
import cheerio from 'cheerio';
export class Reddit extends Component {
constructor(props) {
super(props);
this.state = {
reddit: [],
ready: 0
}
this.getRedditTrending = this.getRedditTrending.bind(this);
}
getRedditTrending = () => {
var results = [];
request('http://old.reddit.com/r/leagueoflegends', function(error, response, html) {
var $ = cheerio.load(html);
console.log('hi')
$("p.title").each(function(i, element) {
var link = 'https://reddit.com' + $(element).children().attr("href");
var title = $(element).children().text();
console.log('hit')
results.push({
link: link,
title: title
})
})
})
this.setState({
reddit: results,
ready: 1,
})
}
componentDidMount(){
this.getRedditTrending()
}
render(){
if (this.state.ready == 1) {
return (
<div>
{<div>{this.state.reddit.map((i, item) => (<div>
<div key={i}>{item.title} </div>
</div>))}</div>}
</div>
)
}
else { return <div>hi</div>}
}
}
It's not giving me an error either. The map function doesn't show anything, but when I replace it with random text like "hello", that does get shown. Appreciate any advice, thanks.
This is my first file with function 1
import React, {Component} from "react";
import axios from 'axios';
import { config } from '../../config/config.js';
class Dashboard extends Component {
constructor(props) {
super(props);
}
componentWillMount(){
var obj = {
campaign:campaignName,
campaignId:campaignId,
clientId:clientId,
clientName:clentName,
end:endDate,
start:startDate,
timeZone:new Date().getTimezoneOffset(),
ReportName:'Chargebacks',
widgetName:'Billing Cycle'
}
var resdata = ChartAPI.widgetApiCalls(config.apiUrl,obj);
console.log(resdata );
}
}
And this is another one with function 2
import axios from 'axios';
function charts(){
this.widgetApiCalls = function(url,parmsobj){
var byresspose=[];
axios.get(url+"/reports",{params:parmsobj})
.then(function(response){
for(var i in response.data){
byresspose.push({"label":"Billing Cycle"+" "+response.data[i].billingCycle,"value":response.data[i].total})
}
console.log(byresspose);
});
return byresspose;
};
}
charts = new charts();
module.exports = charts;
What is the correct way to pass parameter from one function 1 to another function 2?
You need to import your charts module to your Dashboard Component source file:
import ChartsAPI from './charts.js';
And then you will be able to call it on componentWillMount:
var chartsAPI = new ChartsAPI();
chartsAPI.widgetApiCalls(config.apiUrl,obj).then(function(result) {
var resdata = result;
console.log(resdata);
});
This also requires widgetApiCalls to return Promise:
this.widgetApiCalls = function(url,parmsobj){
return axios.get(url+"/reports",{params:parmsobj})
.then(function(response){
var byresspose=[];
for(var i in response.data){
byresspose.push({"label":"Billing Cycle"+" "+response.data[i].billingCycle,"value":response.data[i].total})
}
console.log(byresspose);
return byresspose; // this will come to the Dashboard `widgetApiCalls.then`
});
};
callback
promise
async&await
i prefer the last one.
its a typical Asynchronous problem.
componentWillMount(){
var obj = {
campaign:campaignName,
campaignId:campaignId,
clientId:clientId,
clientName:clentName,
end:endDate,
start:startDate,
timeZone:new Date().getTimezoneOffset(),
ReportName:'Chargebacks',
widgetName:'Billing Cycle'
}
this.getData(config.apiUrl,obj)
}
async getData(url, obj) => {
var resdata = await ChartAPI.widgetApiCalls(url,obj);
console.log(resdata );
}
besides that i think that you don't need to defined chartAPI as a single module.
just defined it in the component