1
With this scolding, I start generating this array with the 60 blank positions (initially)
let [list, setList] = useState(Array(60).fill(""))
Then with this array will serve to generate all 60 "buttons" at each pass of the . map(item.,index). as below:
list.map((item, index) => (
<NumerosParaMarcar index={index} key={index} item={item} />
))
The component: Each button (number)
const NumerosParaMarcar = (props) => {
console.log('=== ', props.index)
return (
< TouchableOpacity
delayPressIn={0}
onPress={() => { marcaNumero(props.index) }}
>
<ImageBackground
style={stylesNumero(props.item).image}
source={Params.imagemBolaBranca}
>
<Text style={stylesNumero(props.item).textNumero}>{(props.index + 1) <= 9 ? "0" + (props.index + 1) : (props.index + 1)}</Text>
</ImageBackground>
</TouchableOpacity >
)
}
Função Marcanumero
const marcaNumero = (index) => {
let numero = (index + 1) <= 9 ? "0" + (index + 1) : (index + 1)
console.log('inicio ', numero)
//-- REGISTRO O NUMERO MARCADO NA POSIÇÃO DO ARRAY
let updateArray = list.map((item, itemIndex) => itemIndex === index ? (item == "" ? numero.toString() : "") : item.toString())
//-- SEPARO SOMENTE OS QUE TEM NUMEROS!
numerosMarcados = updateArray.filter(numero => numero !== "")
let num = numerosMarcados.length
if (num > qtdMaximoMarcar) {
setQtdMarcadas(num - 1)
Toast.showWithGravity('Todos os números já foram marcados ', Toast.LONG, Toast.CENTER)
return;
}
atualizaTituloMsgMarcados()
setNumerosList(numerosMarcados)
setQtdMarcadas(num)
setList(updateArray)
console.log('fim', numerosList)
}
when changing setNumerosList(), you are also running all the code again..
setNumerosList(numerosMarcados)
Main code, where I assemble the components
return (
<SafeAreaView style={styles.layout}>
<View style={[styles.headerRestaMarcar]}>
<View style={styles.viewtextFaltaMArca} >
<Text style={stylesTextoRestaMarcar(qtdMarcadas, qtdMaximoMarcar).textoRestaMarcar}>{msgRestaMarcar}</Text>
</View>
<BotaoMarcar />
</View>
<ScrollView
contentContainerStyle={{
alignItems: "center",
justifyContent: 'center',
flexDirection: "row",
flexWrap: 'wrap',
elevation: 6,
backgroundColor: '#fff',
margin: 5,
borderRadius: 10,
padding: 5
}}
>
{
list.map((item, index) => (
<NumerosParaMarcar index={index} key={index} item={item} />
))
}
</ScrollView>
{qtdMarcadas >= qtdMaximoMarcar && <BotaoSalvarJogada />}
</SafeAreaView >
);
and it’s beautiful so far, I’ve attached the canvas so you can have an idea,
ps... notice this passage:
<ImageBackground
style={stylesNumero(props.item).image}
source={Params.imagemBolaBranca}
>
i pass the current state of the number inside the array.. to check whether it is filled or not.. if filled in, I change the font color to mark the number clicked by the user.
the logic between checking and unchecking, number of numbers already marked.. etc. is working which is a blz.. apart from the fact that I have to redenrize everything OKK!!
abronca is that it gets too slow, takes about 2 seconds. Hence the user will have to mark 12 numbers, gets very bad... not to mention I created a way of the app, play alone for the user, suggest moves.. It takes 12 seconds to fill everything, due to this unnecessary rendering .
THE BRONCA:
Hence I know that changing an array position causes it to process again, but I need you to only change the state of the given button!
The reason is that when I click on the button (number) I change (fill) the position in the array, and in this state change is that the app runs all the code again, rendering all the buttons from 1 to 60 , according to the array (list), already with the positions filled. this fill, affects the color of the number and the opacity of the image (ball)... I pass the contents of the array position to the Styled, and if this past parameter contains a number (ie) is filled... automatically I change the color of the letter to red for example.
When clicking on some number, I fill in the position of the number i.e., if it was the number 4
["","","","04","","".... 60x]
number 07
["","","","04",""",""07".... 60x]
I tried already useMemo(), useEffect().. I tried to make the individual control of each button, but I still could not solve the problem...
I hope I’ve been clear, thank you!!
Complete code:
import React, { useState, useEffect } from 'react';
import {
View,
Text,
StyleSheet,
SafeAreaView,
TouchableOpacity,
ScrollView,
ImageBackground,
Alert
} from 'react-native';
import * as Animatable from 'react-native-animatable';
import Toast from 'react-native-simple-toast';
import { Parse } from 'parse/react-native';
const Params = require('../bin/Parametros')
const Utils = require('../bin/utils')
const MarcarCartelaScreen = ({ navigation }) => {
const qtdMaximoMarcar = Params.qtdMaximoMarcar
const qtdNumerosCartela = Params.qtdNumerosCartela
const [numeroUm, setNumeroUm] = useState("")
const [msgRestaMarcar, setMsgRestaMarcar] = useState("RESTAM " + qtdMaximoMarcar + " NÚMEROS!");
const [qtdMarcadas, setQtdMarcadas] = useState(0)
const [alterouSaldo, setAlterouSaldo] = useState(true)
let [list, setList] = useState(Array(qtdNumerosCartela).fill(""))
const [numerosList, setNumerosList] = useState([])
let numerosMarcados = []
//alterouSaldo && Utils.atualizaSaldoUsuario(navigation)
const zeraMarcacoes = () => {
setList(Array(qtdNumerosCartela).fill(""))
setQtdMarcadas(0)
atualizaTituloMsgMarcados();
}
const salvarJogada = async () => {
let saldoAtaual = Params.saldoUsuarioDecimal - Params.valorJogada
if (saldoAtaual < 0) {
Alert.alert('Atenção!', 'Saldo insuficiente para registrar esta jogada, faça uma recarga e concorra. ', [{ text: 'Ok' }]);
return;
}
const myNewObject = new Parse.Object('jogos');
myNewObject.set('jogo', numerosList);
myNewObject.set('usuario', Parse.User.current());
const usuario = JSON.parse(JSON.stringify(Parse.User.current()));
let User = new Parse.Object('_User');
User.set('objectId', usuario.objectId);
User.set('saldo', saldoAtaual);
try {
await myNewObject.save();
await User.save();
Toast.showWithGravity('Sua jogada foi registrada. Boa sorte! ', Toast.LONG, Toast.CENTER);
zeraMarcacoes()
Params.saldoUsuarioDecimal = saldoAtaual
setAlterouSaldo(true)
} catch (error) {
console.log(error)
Toast.showWithGravity('Algum erro ocorreu, tente mais tarde! ', Toast.LONG, Toast.CENTER);
return;
}
}
const atualizaTituloMsgMarcados = () => {
// console.log('---', numerosMarcados.length)
let restam = qtdMaximoMarcar - numerosMarcados.length
// console.log('resta ---', restam)
let msg = restam > 1 && "RESTAM " + restam + " NÚMEROS!"
msg = restam == 1 ? "RESTA 1 NÚMERO" : msg
msg = restam == 0 ? numerosMarcados.toString().split(",").join(" ") : msg
setMsgRestaMarcar(msg)
}
const marcarAleatorio = () => {
setTimeout(function () {
let num = Math.floor(Math.random() * qtdNumerosCartela + 1)
let numero = (num) <= 9 ? "0" + num : num
let index = num - 1;
if (numerosMarcados.indexOf(numero) > 0) {
marcarAleatorio()
return;
}
let updateArray = list.map((item, itemIndex) => itemIndex === index ? (item == "" ? numero.toString() : "") : item.toString())
//-- SEPARO SOMENTE OS QUE TEM NUMEROS!
numerosMarcados = updateArray.filter(numero => numero !== "")
list[index] = numero
setNumerosList(numerosMarcados)
atualizaTituloMsgMarcados()
if (numerosMarcados.length < qtdMaximoMarcar) {
marcarAleatorio()
} else {
setNumerosList(numerosMarcados)
setQtdMarcadas(numerosMarcados.length)
}
}, 0);
}
const marcaNumero = (index) => {
let numero = (index + 1) <= 9 ? "0" + (index + 1) : (index + 1)
console.log('inicio ', numero)
//-- REGISTRO O NUMERO MARCADO NA POSIÇÃO DO ARRAY
let updateArray = list.map((item, itemIndex) => itemIndex === index ? (item == "" ? numero.toString() : "") : item.toString())
//-- SEPARO SOMENTE OS QUE TEM NUMEROS!
numerosMarcados = updateArray.filter(numero => numero !== "")
let num = numerosMarcados.length
if (num > qtdMaximoMarcar) {
setQtdMarcadas(num - 1)
Toast.showWithGravity('Todos os números já foram marcados ', Toast.LONG, Toast.CENTER)
return;
}
atualizaTituloMsgMarcados()
setNumerosList(numerosMarcados)
setQtdMarcadas(num)
setList(updateArray)
console.log('fim', numerosList)
}
const marcarCartela = () => {
marcarAleatorio()
}
// useEffect(() => {
// //alterouSaldo && Utils.atualizaSaldoUsuario(navigation)
// console.log('uese effect alterasaldo')
// }, [alterouSaldo]);
const NumerosParaMarcar = (props) => {
console.log('=== ', props.index)
return (
< TouchableOpacity
delayPressIn={0}
onPress={() => { marcaNumero(props.index) }}
>
<ImageBackground
style={stylesNumero(props.item).image}
source={Params.imagemBolaBranca}
>
<Text style={stylesNumero(props.item).textNumero}>{(props.index + 1) <= 9 ? "0" + (props.index + 1) : (props.index + 1)}</Text>
</ImageBackground>
</TouchableOpacity >
)
}
const BotaoSalvarJogada = () => {
return (
<Animatable.View
style={styles.footer}
animation="bounceIn">
<TouchableOpacity
style={styles.btSalvarJogada}
onPress={() => { salvarJogada() }}
>
<Text style={styles.textBtSalvarJogada}>SALVAR JOGADA</Text>
</TouchableOpacity>
</Animatable.View>
)
}
const BotaoMarcar = () => {
return (
<Animatable.View
style={styles.viewbtMarcar}
animation="tada">
<TouchableOpacity
style={styles.btMarcar}
onPress={() => { marcarCartela() }}>
<Animatable.Text animation="pulse" easing="ease-out" iterationCount="infinite"
style={{
alignContent: "center",
justifyContent: "center",
fontSize: 55,
textAlign: 'center'
}}></Animatable.Text>
</TouchableOpacity>
</Animatable.View>
)
}
useEffect(() => {
//!mostraBtMarcar && setMostraBtMarcar(true);
console.log('GERAL - MARCAR CATERLA')
}, []);
return (
<SafeAreaView style={styles.layout}>
<View style={[styles.headerRestaMarcar]}>
<View style={styles.viewtextFaltaMArca} >
<Text style={stylesTextoRestaMarcar(qtdMarcadas, qtdMaximoMarcar).textoRestaMarcar}>{msgRestaMarcar}</Text>
</View>
<BotaoMarcar />
</View>
<ScrollView
contentContainerStyle={{
alignItems: "center",
justifyContent: 'center',
flexDirection: "row",
flexWrap: 'wrap',
elevation: 6,
backgroundColor: '#fff',
margin: 5,
borderRadius: 10,
padding: 5
}}
>
{
list.map((item, index) => (
<NumerosParaMarcar index={index} key={index} item={item} />
))
}
</ScrollView>
{qtdMarcadas >= qtdMaximoMarcar && <BotaoSalvarJogada />}
</SafeAreaView >
);
};
// export default React.memo(MarcarCartelaScreen);
export default MarcarCartelaScreen;
const stylesTextoRestaMarcar = (qtdM, qtdMaximoMarcar) => StyleSheet.create({
textoRestaMarcar: {
marginTop: 6,
opacity: qtdM >= qtdMaximoMarcar ? 0.8 : 0.7,
fontSize: 25,
color: qtdM >= qtdMaximoMarcar ? "#FFF" : "#FFF",
textAlign: qtdM >= qtdMaximoMarcar ? "center" : "left",
fontFamily: 'Caramel Sweets',
},
})
const stylesNumero = (item) => StyleSheet.create({
textNumero: {
fontSize: 18,
// marginTop: 13,
marginTop: item === "" ? 13 : 10,
fontFamily: 'Caramel Sweets',
color: item !== "" ? "#ff8080" : "#05375a",
fontFamily: item === "" ? 'Caramel Sweets' : null,
// opacity: item !== "" ? 1 : 0.8,
},
// textNumero: {
// fontSize: item !== "" ? 21 : 18,
// marginTop: item !== "" ? 13 : 10,
// fontFamily: item !== "" ? 'Caramel Sweets' : null,
// color: item !== "" ? "#ff8080" : "#05375a",
// opacity: item !== "" ? 1 : 0.8,
// },
image: {
alignItems: 'center',
width: 45,
height: 45,
backgroundColor: "#FFF",
opacity: item !== "" ? 0.6 : 0.8,
// background: item ? `url(${bolaBranca})` : `url(${bolaMarcada})`,
}
});
const styles = StyleSheet.create({
layout: {
alignItems: "center",
flex: 1,
elevation: 10,
},
header: {
width: "100%",
// backgroundColor: '#FF8C00', //Params.corPrimary,
justifyContent: 'center',
padding: 10,
height: 60,
flexDirection: "row",
},
headerRestaMarcar: {
elevation: 6,
margin: 4,
backgroundColor: "#314968",
paddingLeft: 10,
height: 60,
width: "98%",
// marginBottom: 20,
flexDirection: "row",
borderRadius: 5,
},
textoHeader: {
color: '#CCC',
fontSize: 17,
textAlign: "center",
},
footer: {
width: '100%',
justifyContent: 'center',
alignItems: 'center',
position: 'absolute', //Here is the trick
bottom: 20,
},
btSalvarJogada: {
elevation: 6,
width: '70%',
height: 70,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: "#FF9800",
borderRadius: 25,
borderColor: '#05375a',
borderWidth: 4,
opacity: 0.9
},
textBtSalvarJogada: {
marginTop: 10,
color: '#05375a',
fontSize: 30,
fontFamily: 'Caramel Sweets'
},
viewtextFaltaMArca: {
flex: 1,
alignSelf: "center",
},
viewMsgTitulo: {
alignSelf: "center",
// backgroundColor:"red"
},
viewbtFecharHead: {
flex: 1,
alignSelf: "center",
alignContent: "flex-end",
alignItems: "flex-end"
},
viewbtMarcar: {
alignSelf: "center",
// backgroundColor: "#FFF000",
width: 70,
height: 70,
marginRight: 5
},
btMarcar: {
alignContent: "center",
alignSelf: "center",
alignItems: 'center',
},
});
New code...
import React from 'react';
import { View } from 'react-native';
import styled from 'styled-components/native'
const ButtonDefault = styled.Text`
color: ${props => props.status ? '#ff8080' : '#05375a'}
margin-top: 13px;
fontFamily: 'Caramel Sweets';
font-size: 18px;
`;
const Button = React.memo((props) =>
<>
{console.log("===", props.index)}
<ButtonDefault {...props} />
</>
);
const MarcarCartelaScreen = () => {
console.log('Rodando pagina');
const [list, setList] = React.useState(Array(60).fill(false))
const handleOnClick = React.useCallback((index) => {
console.log("---------------------------cliquei ", index);
let item = [...list];
item[index] = !item[index];
setList(item);
}, [list]);
return (
<View>
{
list.map((i, x) =>
<Button
// onClick={e => handleOnClick(e, x)}
onPress={e => handleOnClick(x)}
status={i}
index={x}
key={x}>
{(x + 1)}
</Button>
)}
</View>
)
};
export default MarcarCartelaScreen;
It even happens that you described because it is reactive from any update it re-mounts the component and performs all functions. One way is using useCallback and memo to decrease and also generate the array of items outside think it improves. You have to assemble in asking a minimal example missing the components to give a better explanation
– novic
I would use an array object I think would look better and the button has to put the code
– novic
Everybody, I’ll edit the question to try to improve...
– Renato Muniz
I don’t know if I made my situation worse :D was worth!! I modified it.
– Renato Muniz
How’s the function code
marcaNumero
?– Isac
In addition to the code of
marcaNumero
, as Isac said, where does this function come from? Also show the parent code of theNumerosParaMarcar
.– Rafael Tavares
the problem must be in logic the markNumer I made an example and I did not have rendering as you showed in the figure.
– novic
I thought about it now, I did not put the Marcanumero... I’m going for now!! , has how to show me and example @novic
– Renato Muniz
I added the main component assembly code!! Obg!!!
– Renato Muniz
your code is totally weird, where you can get
list
inside a component that marks? I believe that is the problem, I created an answer and does not have this problem, but, it is hidden and its code can not reproduce– novic
@novic hello, well.. my idea should be this and so I did... the list is initially created with the 60 blank positions, and with each click on the number, I go there in the list and fill the position of the number, 35 in the 35 position (in case 36, because it starts at the correct zero?... ) every number clicked I go there in position and fill. this fill modification is ta making it process all the code again.... I will put the complete code!!!
– Renato Muniz
help me @novic :( I added the full code
– Renato Muniz
I made the code down there, if you don’t take it negative you can check it out.
– novic
Masssa.. I go from a balcony here and do some testing, bro thanks!!! Jump back here!!! Thanks
– Renato Muniz
Let’s go continue this discussion in chat.
– Renato Muniz
@novic Hello .. do you believe that after some work in adapting to the reac-Active, and after running continues running all the code?? I was pasmo man kkk... but it really got a little more performatic, but if I didn’t perform
– Renato Muniz
is something you’re still missing.
– novic
I can’t imagine! if you need more information here, obg! that version I posted here, was practically yours.
– Renato Muniz