React Native - How to access variable between two buttons - react-native

Trying to learn react native here and want to reuse a variable between two "buttons" to perform tasks.
Take for example a simple workflow:
When the user presses Start a random number is generated and a
message is displayed
When the user presses Check I do some checking and display a
message according to the results.
This is my approach:
state = {
statusText: "Press Start to begin",
randNum: 0,
};
generateRandNum = () => {
var rand = Math.floor(Math.random() * 100);
return rand;
};
pressStart = () => {
this.setState({
randNum: this.generateRandNum(),
statusText: "started; " + randNum, //display randnum for simple check-debug
});
};
pressCheck = () => {
this.setState({
statusText: "checked; ",
});
};
Above, when pressStart is pressed, returns an error saying randNum is not found.
This, however, does work, but now can't access the variable elsewhere
pressStart = () => {
this.setState({
statusText: "started; " + this.generateRandNum(), //display randnum for simple check-debug
});
};
How can I properly update randNum to the generated number so that I can access it globally?
==== While the answer below works this is what I ended up using, which seems to work just the same.
pressCheck = () => {
this.setState({
statusText: "checked; " + this.state.randNum,
});
};

You never initialize randNum anywhere, so in order to use it in both places, you should give it a value before the setState.
Try this :
pressStart = () => {
const randNum = this.generateRandNum()
this.setState({
randNum: randNum,
statusText: "started; " + randNum, //display randnum for simple check-debug
});
};
pressCheck = () => {
this.setState(oldState => ({
...oldState,
statusText: "checked; " + oldState.randNum,
}));
};

Related

How can I refresh datatable in Wire using refreshApex

#wire(_getContacts,{recordId:'$recordId'}) wiredContacts({error,data}){
this.dataToRefresh = data;
if (data) {
this.contacts = this.dataToRefresh.recordList;
this.ContactsRecords = this.dataToRefresh.cList;
this.contactsSize = " Case Contacts (" + this.contacts.length + ")";
}else{
//
}
};
relateContacts() {
this.showSpinner = true;
this.showtable=false;
relateContacts({contacts: this.selected, recordId: this.recordId})
.then(data => {
this.showSpinner=false;
this.showtable=true;
this.showSuccessMessage();
refreshApex(this.dataToRefresh);
//location.reload();
this.isShowModal = false;
})
.catch(error => {
console.log(error);
this.showSpinner=false;
const evt = new ShowToastEvent({
title: 'Application Error',
message: error.body.message,
variant: 'error',
mode: 'sticky'
});
this.dispatchEvent(evt);
this.showSpinner = false;
});
}
For this code, I tried refreshApex with all possible ways. but I'm not sure the miss here. I've Checked all the blogs but everywhere, the solution is mentioned.
Tried refreshApex like below :
#wire(_getContacts,{recordId:'$recordId'}) wiredContacts({data}){
this.dataToRefresh = data;
But this also does not work
Ah that is a fun one ! Your issue is using destructuring in wiredContacts as the parameter.
(The {data} or {data,error} normally works as a parameter to the function being called back, except if you have to do refresh) Try this instead.
#wire(_getContacts,{recordId:'$recordId'}) wiredContacts(value){
this.dataToRefresh = value;
const {data, error} = value;
//Rest of you code now with data and error
}
Then in your other method you can do:
method(){
refreshApex(this.dataToRefresh);
}
Salesforce does show doing this in their example code, but it’s easy to miss and experience the fun you have been having with this.
https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.apex_result_caching
See the last example on their page.

getting undefined on fetching rss feed

I want to randomly display some of the news from a google rss news feed using the url and the package react-native-url-preview. Im doing a fetch call on it:
const [rssFeed, setRssFeed] = useState([]);
const [shouldFetch, setShouldFetch] = useState(true);
var feed = [];
if (shouldFetch) {
console.log("shouldFetch");
getFeed();
setShouldFetch(false);
}
function getFeed() {
console.log("getFeed: " + shouldFetch);
fetch(
"https://news.google.com/rss/search?q=cars&hl=en-GB&gl=GB&ceid=GB%3Aen"
)
.then((response) => response.text())
.then((responseData) => rssParser.parse(responseData))
.then((rss) => {
console.log(typeof rss.items);
let feedItems = rss.items;
feed = feedItems;
// #ts-ignore
setRssFeed(rss.items);
});
}
if (!shouldFetch) {
console.log(rssFeed);
var randomArr = [];
while (randomArr.length < 4) {
var r = Math.floor(Math.random() * 100);
if (randomArr.indexOf(r) === -1) randomArr.push(r);
// #ts-ignore
console.log(r + " " + rssFeed[r].links[0].url);
}
}
This only works sometimes!
50% of the times I get the error: undefined is not an object (evaluating 'rssFeed[r].links'.
I thought this is beacause of the reloading in react-native and this is why i put the if check. But it has not solved it. Any ideas?
You can use optional chaining like rss?.items.
which means if rss is present check for rss.item.
rssFeed?.[r]?.links
Sometimes you get an Undefined Error because the UI gets rendered before the actual data is present.

Testcafe: Is there a method to check for elements visible within the viewport? [duplicate]

I'm trying to implement a custom method to find out if the element is in the current view port
Below is the snippet of code that I've tried to implement but the outcome does not render the boolean result:
export const isElementInViewport = () => {
const getBoundValues = ClientFunction(() => document.querySelectorAll(".hero-getstart").item(0).getBoundingClientRect());
const windowHeight = ClientFunction(() => window.innerHeight);
const windowWidth = ClientFunction(() => window.innerWidth);
return getBoundValues.bottom > 0 && getBoundValues.right > 0 && getBoundValues.left < (windowWidth || document.documentElement.clientWidth) && getBoundValues.top < (windowHeight || document.documentElement.clientHeight);
};
The above code runs properly on the browser console, i.e when I try to store the getBoundValues in a variable A and try to run the return command, it prints the output as true or false depending on the visibility of the element in the viewport but in the script, It always gives a false:
Here's the method which triggers the above method:
export const verifyElementInView = () => {
const elementVisible = isElementInViewport();
console.log(elementVisible);
};
The output is always false.
Here's the snippet of output I receive upon trying to console.log(getBoundValues):
{ [Function: __$$clientFunction$$]
with: [Function],
[Symbol(functionBuilder)]:
ClientFunctionBuilder {
callsiteNames:
{ instantiation: 'ClientFunction',
execution: '__$$clientFunction$$' },
fn: [Function],
options: {},
compiledFnCode: '(function(){ return (function () {return document.querySelectorAll(".hero-getstart").item(0).getBoundingClientRect();});})();',
replicator:
{ transforms: [Array],
transformsMap: [Object],
serializer: [Object] } } }
What am I missing?
There's no need to create a client function for each client-side call. Instead, you can wrap the entire function into the ClientFunction call as follows:
const isElementInViewport = ClientFunction(() => {
const getBoundValues = document.querySelector("#developer-name").getBoundingClientRect();
const windowHeight = window.innerHeight;
const windowWidth = window.innerWidth;
return getBoundValues.bottom > 0 && getBoundValues.right > 0 && getBoundValues.left < (windowWidth || document.documentElement.clientWidth) && getBoundValues.top < (windowHeight || document.documentElement.clientHeight);
});
I recommend that you call your client function as follows (as described in the Executing Client Functions topic):
 
test('ClientFunctionCall', async t => {
const elementVisible = await isElementInViewport();
console.log(elementVisible)
});
 
The following example might also be useful: Complex DOM Queries

Perform a POST request in the background using React Native (expo)

I am relatively new to React Native but I have a functional codebase. My app sends orders from the waiter to the kitchen. I have tested it in stores. What I need is to somehow post the order to my web app without waiting for the server to respond (assuming that all is ok) and navigate directly to the list of tables some sort of async/background job. Do I implement this using some background tasks? if yes could you point in the right direction? Also if possible no redux answers I don't know how to use it yet.
Sorry for the messy code I'm getting better.
onSendOrder = () => {
//console.log('Sending Order');
//console.log("table_id", this.props.navigation.getParam("table_id"));
// trim the contents.
let order_items = this.state.order;
// //console.log(order_items);
// const myArray = this.state.data.filter(function( obj ) {
// return obj.checked !== false;
// });
var i;
// let total_cost = 0;
let contents = []
// //console.log('total_cost: ', total_cost);
// let items = order.items;
for (i = 0; i < order_items.length; i++) {
contents = order_items[i].contents.filter(function( obj ) {
return obj.checked !== false;
});
// //console.log(contents);
order_items[i].contents = contents;
// total_cost += this.compute_item_cost(order[i]);
}
this.setState({loading:true});
//console.log('Trimed order items: ',order_items);
let order = {
"items": {
"credentials": this.state.credentials,
"personnel_id": 1,
"store_id": 1,
"order_comment": "",
"order_id": "",
"timestamp": "None",
"table_id": this.props.navigation.getParam("table_id"),
"order_items": order_items
}
};
var host = this.props.navigation.getParam('url', 'something.com');
// //console.log('SENDING ORDER TO HOST: ', host)
//console.log('ORDER OBJECT', order);
fetch("http://" + host + "/api/v1/mobile/order?store_id=1", {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(order)
})
.then(response => {
// //console.log(response.status)
// this.props.navigation.navigate('Table', { order: this.state.order });
const statusCode = response.status;
const data = response.json();
return Promise.all([statusCode, data]);
})
.then((server_response) => {
//console.log("RESULTS HERE:", server_response[0])
this.setState({
order: [],
}, function () {
if (server_response[0] == 201) {
//console.log('Success Going to Table')
this.props.navigation.navigate('Table', { order: this.state.order });
} else {
//console.log('Failed going to table')
this.props.navigation.navigate('Table', { order: this.state.order });
}
});
})
.catch((error) => {
//console.error(error);
})
};
}
import * as Notifications from 'expo-notifications';

App crash only if im not using debugger. Unable to overcome the situation. What should I do?

I'm facing a pretty ugly issue that I'm not able to overcome by myself, I just don't get it.
A short summary of my app purpose: You can find food around and make orders to restaurant owners.
I wrote a helper function that allows me to decide if the restaurant is open or closed based on its schedule “horarioSemanal” property.
This function take the restaurants queried from firestore as arguments and depending in some conditions it decide which value of the property “disponible” (available) it deserves.
The thing is that it works pretty well! So well that I published the changes through expo, and as expo has updates over-the-air and I have my app in both apptore and Google play it reached all my users…
None of my users were able to use my app until I removed the changes because I was unable to detect the issue. In my simulator it worked 100% but when the app was deployed crashed almost instantly.
Testing, testing, and testing I finally come to the issue but I still can't figure out what the hell should I do to overcome this situation.
The app while I use the js debugger it works perfectly! but when I turned off this new module I wrote doesn't work.
I recorded a video so you can see the same I'm watching on my screen:
https://www.youtube.com/watch?v=x9-t8-3XzKc
this is the action where im dispatching the action:
import { restaurantesHorarioValidado, validaDisponibilidadComidas } from '../../src/3-ResultadosComponents/Librerias/DisponibilidadHorario';
export const searchResultsInLocation = (ubicacion) => {
const db = firebase.firestore();
const docRef = db.collection('Restaurantes').where('abierto', '==', true).where(`zonaOperativa.zonaConsulta.${ubicacion}`, '==', true).get();
const restaurantesIDS = [];
return (dispatch) => {
const holder = [];
dispatch({
type: BUSQUEDA_DE_RESULTADOS,
});
docRef.then(querySnapshot => {
querySnapshot.forEach(doc => {
holder.push(doc.data());
restaurantesIDS.push(doc.data().id);
});
dispatch({
type: DESCARGA_RESTAURANTES_ABIERTOS,
restaurantes: restaurantesHorarioValidado(holder)
});
})
.then(() => {
const comidasRefs = [];
restaurantesIDS.forEach(restaurant => {
const ref = db.collection('Comidas').where('restaurantID', '==', `${restaurant}`).get();
comidasRefs.push(ref);
});
return Promise.all(comidasRefs).then(results => {
const comidas = [];
results.forEach(resto => {
resto.forEach(comida => comidas.push(comida.data()));
});
dispatch({
type: DESCARGA_COMIDAS,
comidas: validaDisponibilidadComidas(comidas, restaurantesHorarioValidado(holder))
});
})
.then(() => dispatch({
type: BUSQUEDA_DE_RESULTADOS,
}))
.catch(err => console.log('error; ', err));
});
};
};
here is how the reducer is handling the action:
case DESCARGA_COMIDAS:
return { ...state, comidas: action.comidas };
case DESCARGA_RESTAURANTES_ABIERTOS:
return { ...state, restaurantes: action.restaurantes };
this is the module I wrote and I'm using to create the object that the action creator send:
const diasDeSemana = ['Domingo', 'Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sabado'];
const today = new Date().getDay();
const hoyAbre = (horario) => {
if (horario) {
const JornadaHoy = horario.find(jornada => jornada.dia == diasDeSemana[today]);
return JornadaHoy;
}
return false;
};
export const isRestaurantAvalaible = (horario) => {
const Today = new Date();
if (hoyAbre(horario)) {
//Si el restaurant abre hoy
//Evalua si está abierto
const horarioApertura = () => {
const nuevoDia = new Date(`${Today.getFullYear()}, ${Today.getMonth() + 1} ${Today.getDate()} ${hoyAbre(horario).horario.apertura}:00`);
return nuevoDia;
};
const horarioCierre = () => {
//Si horario de cierre es hoy
const nuevoDia = new Date(`${Today.getFullYear()}, ${Today.getMonth() + 1} ${Today.getDate()} ${hoyAbre(horario).horario.cierre}:00`);
//Si el horario de cierre de hoy es pasado las 00:00
const cierraTomorrow = new Date(`${Today.getFullYear()}, ${Today.getMonth() + 1} ${Today.getDate() + 1} ${hoyAbre(horario).horario.cierre}:00`);
if (nuevoDia.getHours() <= 8) {
return cierraTomorrow;
}
return nuevoDia;
};
const isNowOpen = Today.getTime() >= horarioApertura().getTime();
const isNowClosed = Today.getTime() >= horarioCierre().getTime();
//Si está abierto
if (isNowOpen && !isNowClosed) {
return { estado: 'abierto' };
}
//Si abre mas rato
if (hoyAbre(horario) && (Today.getTime() < horarioApertura())) {
return { estado: 'abre pronto', horarioApertura: horarioApertura() };
}
//Si ya cerró
if (isNowOpen && isNowClosed) {
return { estado: 'ya cerro', horarioCierre: horarioCierre() };
}
}
//Si hoy no abre
if (!hoyAbre(horario)) {
return { estado: 'No abre hoy' };
}
};
export const restaurantesHorarioValidado = (restaurantes) => {
const restaurantesModificados = restaurantes.map(restaurant => {
return { ...restaurant, disponible: isRestaurantAvalaible(restaurant.horarioSemanal) };
});
const restaurantesAbiertos = restaurantesModificados.filter(restaurant => restaurant.disponible.estado == 'abierto');
const restaurantesProximosAbrir = restaurantesModificados.filter(restaurant => restaurant.disponible.estado == 'abre pronto');
const restaurantesCerrados = restaurantesModificados.filter(restaurant => restaurant.disponible.estado == ('ya cerro' || 'No abre hoy'));
return [...restaurantesAbiertos, ...restaurantesProximosAbrir, ...restaurantesCerrados];
};
export const validaDisponibilidadComidas = (comidas, restaurantes) => {
//Se le agrega la propiedad "disponible" del restaurant dueño
const comidasModificadas = comidas.map(comida => {
const Owner = restaurantes.find(restaurant => restaurant.id == comida.restaurantID);
return { ...comida, disponible: Owner.disponible };
});
const comidasDisponibles = comidasModificadas.filter(comida => comida.disponible.estado == 'abierto');
const comidasProximosAbrir = comidasModificadas.filter(comida => comida.disponible.estado == 'abre pronto');
const comidasNoDisponibles = comidasModificadas.filter(comida => comida.disponible.estado == ('ya cerro' || 'No abre hoy'));
return [...comidasDisponibles, ...comidasProximosAbrir, ...comidasNoDisponibles];
};
this is the error I get once I turned off the js debugger:
[Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'restaurant.disponible.estado')]
Stack trace:
src/3-ResultadosComponents/Librerias/DisponibilidadHorario.js:65:98 in <unknown>
src/3-ResultadosComponents/Librerias/DisponibilidadHorario.js:65:62 in restaurantesHorarioValidado
store/actions/2-ResultadosActions.js:55:50 in <unknown>
node_modules/promise/setimmediate/core.js:37:14 in tryCallOne
node_modules/promise/setimmediate/core.js:123:25 in <unknown>
...
As it suggest there is some error with promises I tried making those functions work as promises. The errors disappear but the I didn't get the object back...
The question is this How the hell may this work just when the debugger it's on and not when it's turned off?
what should I do to get my life back?