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 });
Related
I am unable to fetch firebase child data with React and Redux-Saga. Can you please check the below code ? Why it is not working with redux-saga.
import { takeLatest, put, call, fork, all, take } from "redux-saga/effects";
import { getContactsSuccess, getContactsFail } from "./actions";
import * as types from "./actionTypes";
import firebaseDb from "../firebase";
export function* onGetContactsStartSync() {
try {
const snapshot = yield firebaseDb.child("contacts").on("value");
yield put(getContactsSuccess(snapshot.val()));
console.log("snapshot", snapshot);
} catch (error) {
yield put(getContactsFail(error));
}
}
export function* onLoadContacts() {
yield takeLatest(types.GET_CONTACTS_START, onGetContactsStartSync);
}
const contactSagas = [fork(onLoadContacts)];
export default function* rootSaga() {
yield all([...contactSagas]);
}
When I tried with redux-thunk then I was able to fetch the data from firebase with the below approach
export const getContacts = () => {
return function (dispatch) {
dispatch(getContactsStart());
firebaseDb.child("contacts").on("value", (snapshot) => {
try {
if (snapshot.val() !== null) {
dispatch(getContactsSuccess(snapshot.val()));
} else {
dispatch(getContactsSuccess({}));
}
} catch (error) {
dispatch(getContactsFail(error));
}
});
};
};
So, what is going wrong with redux-saga approach ? I wanted to replicate the same thing with redux-saga.
I think i am missing some small thing here, which is might be very basic. Let me know if have some solution.
I tried the below approach as well.
function createContactChannel() {
const listener = eventChannel((emit) => {
firebaseDb.child("contacts").on("value", (data) => {
if (data.val() !== null) {
emit(data.val());
}
});
return () => firebaseDb.child("contacts").off(listener);
});
console.log("listener", listener);
return listener;
}
export function* onGetContactsStartSync() {
try {
const contacts = createContactChannel();
yield put(getContactsSuccess(contacts));
} catch (error) {
yield put(getContactsFail(error));
}
}
I want to Set a Value and Get it in Render with one line code, by adding a Variable between tags. This could shows error :(Can't find variable: storage_key)
import React, { Component } from 'react'
import { View, Text } from 'react-native';
import AsyncStorage from '#react-native-async-storage/async-storage';
class SyncRu extends Component {
state = {
'storage_Key': ''
}
render() {
const storeData = async (value) => {
try {
await AsyncStorage.setItem('#storage_Key', value)
} catch (e) {
// saving error
}
}
const getData = async () => {
try {
const value = await AsyncStorage.getItem('#storage_Key')
if (value !== null) {
// value previously stored
}
} catch (e) {
// error reading value
}
}
return (
<View>
<Text>
{storage_Key}
</Text>
</View>
)
}
}
export default SyncRu
You have initialized the state incorrectly. Instead of:
state = {
'storage_Key': ''
}
You have to use:
this.state = {storage_Key: ""};
After you access your data from AsyncStorage you have to use setState, for updating your UI.
const value = await AsyncStorage.getItem('#storage_Key')
if (value !== null) {
this.setState({
storage_Key: value
});
}
Also have a look at the documentation of React State.
React State Documentation
I want to make a function in react that get called on every component that need the data to be fetched. I tried this by the way but it returns a Promise type and not the data I need. Instead if I do console.log(res.data.user) it brings the data. Why I cannot return and have it ready to be implemented in every component I need?
import React, { Component } from 'react';
import { useQuery } from "#apollo/react-hooks";
import query from './queries/CurrentUser';
import receive_client from "./Client";
const CurrentUserQuery = async function () {
const client = receive_client()
const result = await client.query({ query: query }).then((res) => {
return res.data.user
})
}
export default CurrentUserQuery;
and here I call it
import React, { Component } from 'react';
import CurrentUser from '../../CurrentUserQuery'
class Home extends Component {
render(){
console.log(CurrentUser())
return(
<div></div>
)
}
}
It looks like you aren't returning from your CurrentUserQuery function,
const CurrentUserQuery = async function () {
const client = receive_client()
const result = await client.query({ query: query }).then((res) => {
return res.data.user
})
if(result){
return result
}
}
The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
In CurrentUserQuery function you should use either await or then().
const CurrentUserQuery = async function () {
try{
const client = receive_client()
const response = await client.query({ query: query })
return {success: true, user:response.data.user}
}catch (err){
return {success: false}
}
}
export default CurrentUserQuery;
/* CurrentUser function return a promise. To get the resolved
value you have to pass a callback to 'then()'
which will be executed the callback once the promise is resolved.
*/
class Home extends Component {
componentDidMount(){
CurrentUser().then(({user, success}) => {
if(success)this.setState({user})
})
}
//.... Rest Of Code .....
}
I am making auth component using react-native.
And the code below sends to 'MainTab' of 'this.props.navigation' depends on the result of axios.
<TouchableOpacity onPress={this.handleSubmit}>
<Text>Save</Text>
</TouchableOpacity>
handleSubmit = () => {
const result = await axios.post(
'http://192.0.0.1:4000/clients',
users
);
if (result.data.success) {
return this.props.navigation.navigate('MainTab');
}
return false
};
But I want to use handleSubmit at an other 'js' file to avoid doing repeatedly.
Thus, I edit a code like below.
import { saveSettings } from '../../storage/settingsStorage'
handleSubmit(): void {
saveSettings(this.state);
}
// in 'settingsStorage.js'
export const saveSettings = async users => {
try {
const result = await axios.post(
'http://192.0.0.1:4000/clients/token',
users
);
if (result.data.success) {
return this.props.navigation.navigate('MainTab');
}
return false
} catch (e) {
console.log(e);
}
};
And in this case, I know 'this.props' can't be passed in normal Js file without passing props. But I don't know how can I pass the props?
Thank you so much for reading this.
Based on your description I think you can just add a second parameter to saveSettings and pass the navigation object through:
import { saveSettings } from '../../storage/settingsStorage'
handleSubmit(): void {
saveSettings(this.state, this.props.navigation);
}
// in 'settingsStorage.js'
export const saveSettings = async (users, navigation) => {
try {
const result = await axios.post(
'http://192.0.0.1:4000/clients/token',
users
);
if (result.data.success) {
return navigation.navigate('MainTab');
}
return false
} catch (e) {
console.log(e);
}
};
Instead of passing navigation prop you can use a technique Navigating without the navigation prop as described in official site .
App.js
import { createStackNavigator, createAppContainer } from 'react-navigation';
import NavigationService from './NavigationService';
const TopLevelNavigator = createStackNavigator({
/* ... */
});
const AppContainer = createAppContainer(TopLevelNavigator);
export default class App extends React.Component {
// ...
render() {
return (
<AppContainer
ref={navigatorRef => {
NavigationService.setTopLevelNavigator(navigatorRef);
}}
/>
);
}
}
we define NavigationService which is a simple module with functions that dispatch user-defined navigation actions.
/ NavigationService.js
import { NavigationActions } from 'react-navigation';
let _navigator;
function setTopLevelNavigator(navigatorRef) {
_navigator = navigatorRef;
}
function navigate(routeName, params) {
_navigator.dispatch(
NavigationActions.navigate({
routeName,
params,
})
);
}
// add other navigation functions that you need and export them
export default {
navigate,
setTopLevelNavigator,
};
Now use it every where without navigation prop
// any js module
import NavigationService from 'path-to-NavigationService.js';
// ...
NavigationService.navigate('MainTab');
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.