Error: Maximum update depth exceeded. React Native - react-native

I try to setState in compenetDidUpdate but it shows error infinite loop. Got any solution? Originally I put the setState in a function but also face this error. I am using class component code
componentDidUpdate(){
if(isEmpty(this.props.AESDetail) == false){
if(this.props.AESDetail.length != 0){
if(this.props.APIESDetail.length != 0){
if(this.props.APIESDetail.Focus != null){
this.setState({
gotFocusApies: true
})
}
}
}
}
}
Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

It looks like you might just need one additional test to make sure gotFocusApies isn't already true.
These if statements are also probably better off combined into one.
Note: list.length != 0 can typically be replaced with list.length or !!list.length.
componentDidUpdate() {
if (
isEmpty(this.props.AESDetail) == false &&
this.props.AESDetail.length &&
this.props.APIESDetail.length &&
this.props.APIESDetail.Focus != null &&
!this.state.gotFocusApies
) {
this.setState({ gotFocusApies: true });
}
}

Related

Why is setting state on array not working?

I am trying to make a system where you would pass in a bunch of coins and they would get added to the state array (selectedTickers). Once I would set selectedTickers to another array, it would still print out the original array. Anyone know how to get this to print out the new array?
Code:
function addTickerToList(ticker) {
const exists = selectedTickers.filter((a) => a === ticker);
console.log(exists);
if (exists.length > 0) {
console.log("first");
let newList = selectedTickers.filter((a) => a !== ticker);
setSelectedTickers(newList);
console.log(selectedTickers);
} else {
console.log("second");
console.log(ticker);
selectedTickers.push(ticker);
}
}
setSelectedTickers is asynchronous.
You are logging selectedTickers before the function fully executed, try to log it on the web page to ensure that the re-render is done.

$refs are null after route change

I have a keyboard navigation system. When you press ArrowUp or ArrowDown, an event is emitted FROM app.js (best place I found to listen to these keypresses since they need to be system-wide) TO the mounted() in the component.
The Event.$on() INSIDE the mounted() part of the component then calls a function that uses $refs to identify the currently selected item and, when ENTER is pressed, show it's modal.
app.js code (listen to the keypresses):
else if (event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'Enter') {
event.preventDefault()
switch (this.$router.currentRoute.path) {
case "/pedidos":
Event.$emit('navegarSetasPedidos', event.key)
break;
case "/clientes":
Event.$emit('navegarSetasClientes', event.key)
break;
}
}
mounted() section of the component in question:
mounted() {
Event.$on('navegarSetasPedidos', (key) => {this.navegarSetas(key)})
}
function responsible for the navigation (sorry for bad formating, haven't figured how stackoverflow's codeblock thing works yet):
navegarSetas(key) {
if (this.navegacaoSetasAtiva == false) {
this.navegacaoSetasAtiva = true
this.navegacaoAtual = 0
} else if (this.modalAtivado == false && this.navegacaoSetasAtiva == true) {
if (key == 'ArrowDown' && this.navegacaoAtual < this.pedidos.length - 1) {
this.navegacaoAtual++
let elementoSelecionado = this.$refs['pedido'+this.navegacaoAtual][0].$el
let boundaries = elementoSelecionado.getBoundingClientRect()
if (boundaries.top < 0 || boundaries.top > (window.innerHeight || document.documentElement.clientHeight)){
elementoSelecionado.scrollIntoView({behavior: 'smooth'})
}
} else if (key == 'ArrowUp' && this.navegacaoAtual <= this.pedidos.length && this.navegacaoAtual > 0) {
this.navegacaoAtual--
let elementoSelecionado = this.$refs['pedido'+this.navegacaoAtual][0].$el
let boundaries = elementoSelecionado.getBoundingClientRect()
if (boundaries.top < 0 || boundaries.top > (window.innerHeight || document.documentElement.clientHeight)){
elementoSelecionado.scrollIntoView({behavior: 'smooth'})
}
} else if (key == 'Enter') {
let pedidoSelecionado = this.pedidos[this.navegacaoAtual].id
Event.$emit('changeShow', pedidoSelecionado)
}
}
This works very well the first time it is acessed. The problem is, if I change the current route to show another component and then return to the previous component, I get a lot of "this.$refs['pedido'+this.navegacaoAtual][0].$el is undefined" errors, but the system still works normally, albeit erratically.
The funny thing is: if I console log "this.$refs['pedido'+this.navegacaoAtual][0].$el is undefined", I'll get an EMPTY log before the errors, then ANOTHER one right below it, this time, not empty.
Everywhere else I've searched this says that the problem is due to how Vue re-renders things, and that I'm calling this event BEFORE it's rendered, which shouldn't be possible since I'm calling it inside mounted().
Any help is greatly appreciated, thank you!
Turns out, after a LOT of searching, the Event.$on event setters also work as the normal JavaScript ones (which makes a lot of sense now that I'm thinking about it)—meaning that you have to destroy them whenever your component is unmounted (aka Destroyed).
Even though VUE Dev Tools was picking only one event after the re-route, it was still firing two (seen through console.log() returning one empty value, a bunch of errors, and another value with filled array AFTER the errors).
The solution to this was simply adding Event.$off('eventName') on the destroyed() function of the component.

Using if else statement in renders block in react native

This is my render function
render () {
return (
<CheckoutView>
<CheckoutActionButton onPress={this.props.navigateSplitTender}><CheckoutActionButtonLabel>Partial Card Payments</CheckoutActionButtonLabel></CheckoutActionButton>
</CheckoutButtonArea>
<CheckoutButtonArea>
{if (this.props.env !== 'Production')
<CheckoutActionButton onPress={this.props.navigateMockPayment}><CheckoutActionButtonLabel>Mock Payments</CheckoutActionButtonLabel>}</CheckoutActionButton>}
</CheckoutButtonArea>
</CheckoutActionArea>
</CheckoutView>
)
}
What I am trying to do is if the environment is not Production, I am trying to navigate the mockpayment page. But it is not showing up, where I am getting worng?
i think you might have forgot to close your condition on the if statement
{if (this.props.env !== 'Production')
you need a curly bracket to close everything up
The <CheckoutActionButton.. is not inside of if block, using shorthand condition is better.
render () {
return (
<CheckoutView>
<CheckoutActionButton onPress={this.props.navigateSplitTender}><CheckoutActionButtonLabel>Partial Card Payments</CheckoutActionButtonLabel></CheckoutActionButton>
</CheckoutButtonArea>
<CheckoutButtonArea>
{this.props.env !== 'Production' && <CheckoutActionButton onPress={this.props.navigateMockPayment}><CheckoutActionButtonLabel>Mock Payments</CheckoutActionButtonLabel>}</CheckoutActionButton>}
</CheckoutButtonArea>
</CheckoutActionArea>
</CheckoutView>
)
}
If it's not working. Try to log this.props.env to make sure it not "Production"

How to check if a component has a signal?

There is a reliable way to check from QML/JavaScript if a component has a signal?
At the moment I found that this code work as intended:
if (myCustomComponent.myCustomSignal)
myCustomComponent.myCustomSignal();
Where myCustomComponent is even as simple as this:
Item {
id: root
signal myCustomSignal()
}
The signal is executed only if myCustomComponent has it but I'm not sure if is the correct way.
No, more reliable way should be to check if component has a signal could be:
if (typeof root.myCustomSignal !== 'undefined' && typeof root.myCustomSignal === 'function') { ... }
or
if (typeof root.myCustomSignal === 'function') { ... }
Using boolean is not realiable. Change your sample target item to:
Item {
id: root
property bool myCustomSignal: true
}
In this case your condition will be true and you will try invoke a property what will lead to crash.
This approach is less error prone and it ensure that signal exists and is invokable/function.

How to clear state when statesave page no longer exists in datatables?

My datatables is declared in this way:
"processing": true
,"serverSide": true
,"stateSave":true
,"stateDuration": 60*60*24
,"ajax":{
"url":"/approval/search.json"
,"type":"post"
}
My code to clear state:
if(page doesn't exist){
table.state.clear();
table.draw()
}
I don't know how to tell if page doesn't exist. I've tried table.page.info() but the data it shows is the same whether the page has info or not.
After SO MUCH trial and error I finally succeeded with this:
,"fnDrawCallback":function(){
if(table.row().data()===undefined){
table.state.clear();
location.href=url
}
}
Updated answer for newer versions of datatables:
drawCallback: function (settings) {
let api = this.api();
// fix pagination if saved page is empty
if (api.page() > 0 && api.rows({page: 'current'}).count() === 0) {
api.page('previous').state.save();
location.reload();
}
}
This will set the state to the previous page if the current does not exist, and reload the page.
I may have used the previous answer and alter it. It work perfectly for me :
drawCallback: function (settings) {
let api = this.api();
var info = api.page.info();
if (info.pages!=0 && (api.page() > 0 && api.rows({page: 'current'}).count() === 0)) {
api.page('first').state.save();
window.location.reload();
}
}