Render if prop changes in React Native Function - javascript

is it possible, in a React Native Function, to render the "return" at changes?
What I try:
I have a Function - this Function gets an specific array out of another Function - on Button Press I generate a new Index - now what I want is to re-render the View to display the array element with the new Index:
const generateNewIndex = function (item) {
return Math.floor(Math.random() * item.length);
};
const PositionItem = ({ arr, position, navigation }) => {
let { name, beschreibung, arten, rooms, isStarred } = position;
let testArray = arr;
let i = 0;
return (
<View style={styles.posContainer}>
<View style={styles.titles}>
<Text style={styles.title}>{name}</Text>
<Text style={styles.subtitle}>{beschreibung}</Text>
<Text style={styles.title}>{testArray[i].name}</Text>
</View>
<View style={styles.buttonsContainer}>
<StyledButton
type="primary"
content={"Next Random Position"}
onPress={() => {
console.warn("Pressed");
i = generateNewIndex(testArray);
}}
/>
</View>
</View>
);
};
export default PositionItem;
Thanks in advance!

I have found a way which is Working.
If anyone wonders in the Future what I did:
add a Use State component:
const [count, setCount] = useState(0);
onPress on Button increase the Count:
onPress={() => {
i = generateNewIndex(array);
setCount((prevCount) => prevCount + 1);
}}

Related

how to assign each list item to the same button in react native

this is my
homePage
as you can see I have some items and a button that I use to add them to the chartScreen, which is chartScreen , I'm using context api to store items in cartContext.js where each item has its own key to make things easier but I cannot correlate the logic for how to assign each item to the button so whenever I press the button its own item gets added to the chartScreen.
const CartContext = createContext();
export function CartProvider({ children }){
const [items, setItems] = useState(
[
{
title: "Pınar",
text: "Pınar Klasik Dana Sucuk (225g)",
pic: <Image
style={styles.image1}
source={require("./Images/klasik_dana_sucuk_paket.png")} />,
key: 1,
},
{
text: "Pınar Uzun Sosis (225g)",
pic: <Image
style={styles.image1}
source={require("./Images/pinar_uzun_sosis.png")} />,
key: 2,
},
]
const [store, setStore] = useState([]);
const addToCart = (text) => {
setStore((prevState) => [
...prevState,
text,
]);
}
return (
<CartContext.Provider value={{items,setItems, addToCart, store}}>
{children}
</CartContext.Provider>
)
I found a cheeky way to send a specific item from addButton.js
const AddButton = () => {
const { items } = useContext(CartContext);
const { addToCart } = useContext(CartContext);
return (
<TouchableOpacity style={styles.button} onPress={() => addToCart(items[0])}>
<Text>+</Text>
</TouchableOpacity>
)
}
and in the chartScreen I view it just like this
const ChartScreen = () => {
const { store } = useContext(CartContext);
if(store.length != 0) {
return (
<FlatList
data={store}
renderItem={({ item }) => (
<View style={styles.listItem}>
<Text style={styles.itemText}>{item.pic} {item.text}</Text>
</View>
)}
/>
)
}
this is for sure not even the wrong way to achieve the goal so can you help me?
You can import your button and make it common for all the items, and pass the value to it.
Here is your button code
const AddButton = ({item}) => {
const { items } = useContext(CartContext);
const { addToCart } = useContext(CartContext);
return (
<TouchableOpacity style={styles.button} onPress={() =>
addToCart(item?.text)}>
<Text>+</Text>
</TouchableOpacity>
)
}
Here you can make button for all you item
const ChartScreen = () => {
const { store } = useContext(CartContext);
if(store.length != 0) {
return (
<FlatList
data={store}
renderItem={({ item }) => (
<View style={styles.listItem}>
<Text style={styles.itemText}>{item.pic} {item.text}</Text>
<AddButton item={item} />
</View>
)}
/>
)
}

change state for a specific children in a loop with "useState"

I am using React native and
I have a loop in which some property types are being displayed,
i created only one state for it because property types are being fetched from DB.
What i want to do is to show them selected. kindly show me a way to achieve it.
const [propBCol, setPropBCol] = useState('#EDEDEE');
const [propTCol, setPropTCol] = useState('#000000');
{propType.map((item, index) => {
return (
<TouchableOpacity style={{
backgroundColor: propBCol,
...ListingFilterStyles.filterAnyBtn,
...ListingFilterStyles.btnMale,
}}
onPress={() => proptypes(item)}>
<Text style={{color: propTCol}}>{item.value}</Text>
</TouchableOpacity>
);
})}
the propTypes function:
const proptypes = item => {
setPropBCol('red');
setPropTCol('White')
}
enter code here
How can i change the selected item color, by above code all are item colors are being changed
const [propBCol, setPropBCol] = useState('#EDEDEE');
const [propTCol, setPropTCol] = useState('#000000');
const [selected, setSelected] = useState([]);
{propType.map((item, index) => {
return (
<TouchableOpacity style={{
backgroundColor: selected.includes(index) ? propBCol : item.propBCol,
...ListingFilterStyles.filterAnyBtn,
...ListingFilterStyles.btnMale,
}}
onPress={() => proptypes(index)}>
<Text style={{color: selected.includes(index) ? propTCol : item.propTCol}}>{item.value}</Text>
</TouchableOpacity>
);
})}
const proptypes = (index) => {
setSelected(prev => {
return [
...prev,
index
]
})
}
You should not declare a state for each one of the propType you are receiving. What you can do is, you can add a key inside the object that you are getting and saving it inside the state.
And on press you can change the value of the checked key using simple index values of the array. You have to pass the data inside the method and write the method as below
const propsTypes = (item, index) => {
var propTypesVar = [...propTypes]
propTypesVar[index].propBCol= <<Your desired color>>
propTypesVar[index].propTCol= <<Your desired color>>
setPropType(propTypesVar)
}
After that the value of propBCol will be inside the object of your propType array and you can render anything to show the user if the value is selected or not i.e.
{propType.map((item, index) => {
return (
<TouchableOpacity
style={{
backgroundColor: item.propBCol,
...ListingFilterStyles.filterAnyBtn,
...ListingFilterStyles.btnMale,
}}
onPress={() => proptypes(item)}>
<Text style={{color: item.propTCol}}>{item.value}</Text>
</TouchableOpacity>
);
})}

How to prevent page refresh on button click in React Native function

In the below React Native function we want to stop random array from initializing on every button click. Currently when we press the button the counter gets incremented as well as the array get initialized again. Any help would be greatly appreciated.
import React, { useState } from "react";
import { Button, Text, View } from "react-native";
const Game1 = (props) => {
const [count, setCount] = useState(0);
handlePress = () => {
// if (selectedNoArry == 0) {
setCount(count + 1);
// selectedNoArry.concat(index);
// console.log(selectedNoArry);
// }
//return false;
};
const randomNoArry = Array.from(
{length: props.randomnno},
x => 1 + Math.floor(10 * Math.random()),
);
return (
<View>
<Text style={{marginTop: 40}}>
you hit {count}!
</Text>
<Text style={{marginTop: 40}}>
this is randomn {randomNoArry}!
</Text>
<Button style={{marginTop: '40'}}
onPress={() => handlePress()}
title="click Me"
/>
</View>
);
}
const Game = () => {
return (
<>
<Game1 randomnno="6" />
</>
);
}
export default Game;
To test please copy paste above code here
You can put the data in useRef() or useState() to prevent it from regenerated automatically.
import React, { useState } from "react";
import { Button, Text, View } from "react-native";
const genRanArr = (length) =>
Array.from({ length: length }, (x) => 1 + Math.floor(10 * Math.random()));
const Game1 = (props) => {
const [count, setCount] = useState(0);
const [randomArray, setRandomArray] = useState(genRanArr(props.name));
const handlePress = () => {
setCount(count + 1);
};
return (
<View>
<Text style={{ marginTop: 40 }}>you hit {count}!</Text>
<Text style={{ marginTop: 40 }}>this a randomn {randomArray}!</Text>
<Button
style={{ marginTop: "40" }}
onPress={() => handlePress()}
title="click Me"
/>
</View>
);
};
const Game = () => {
return (
<>
<Game1 name="6" />
</>
);
};
export default Game;

why wont my set interval work in react native app?

so im working on making a timer count down from some given amount of time which is determined by a slider.
then one can click a start button starting at the slider's value, and begin the count down.
(as it is though, im just working with set values, which I will then somehow link up this slider)
ive been working around this setinterval() func just to see if I can make it count down from 60. but after a few seconds it starts to count radically. i think it has to do with my lack of understanding of state and the way it renders the state repeatedly, or something.
---just learning so bear with the irationality of this code, criticism is apprecieated!---
export const Timer = ({navigation}) => {
const [minutes, setMin] = useState(30);
const [seconds, setSeconds] = useState(60);
let value = 30;
const handleSliderChange = (value) => {
setMin(value)
}
function minusSecond() {
setSeconds(seconds- 1)
}
return(
<View style={styles.Timer}>
<Text style={styles.Txt2}>M I N U T E S</Text>
<View style={styles.Slider}>
<Slider
style={{width: 300, height:40}}
minimumValue={5}
maximumValue={120}
value={value}
step={5}
thumbTintColor='white'
minimumTrackTintColor="#FFFFFF"
maximumTrackTintColor="#000000"
onValueChange={handleSliderChange}
/>
</View>
<View>
<Text style={styles.Time}>
{minutes}:{seconds}
</Text>
</View>
<View style={styles.Start}>
<TouchableOpacity style={styles.buttonStyle} title="Start" onPress={setInterval(setSeconds, 1000)}}>
<Text style={styles.ButtonTxt}>START</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.buttonStyle } title="Home Page">
<Text style={styles.ButtonTxt}>STOP</Text>
</TouchableOpacity>
</View>
</View>
)
}
Your countdown timer logic should look something like this:
const [countDown, setCountDown] = React.useState(60);
const [startTimer, setTimer] = React.useState(false);
React.useEffect(() => {
let timer = setInterval(() => {
if (startTimer) {
setCountDown(countDown > 0 ? countDown - 1 : 0);
}
}, 1000);
return () => {
clearInterval(timer);
};
}, [countDown, startTimer]);
const resetCountDown = () => {
setCountDown(60);
};
Check out the example project below for a live demo.
https://snack.expo.io/#bapeter01/countdown-example

Reset state after unmount screen - Hooks?

After getting data from API I set it to state, and render items in Flatlist,
when I select any item from it I manipulate data and add a new property to item object named as "toggle: true"
and it's works well when I select any item from list I add a border based on toggle,
But when I go back to previous screen then re open the lists screen I can see the border rendered around the items, although I reset the state when the unmounted screen
So what's the wrong I made here?
Code snippet
Data
export default {
...
services: [
{
id: 0,
name: 'nameS0',
logo:
'https://cdn2.iconfinder.com/data/icons/hotel-98/64/hair-dryer-tools-beauty-hairdressing-512.png',
price: 19.99,
},
],
employees: [
{
id: 0,
name: 'name0',
img:
'https://www.visualelementmedia.com/wp-content/uploads/2015/04/person-4-400x629.jpg',
},
...
],
};
const VendorProfile = ({navigation}) => {
const [services, setServices] = React.useState(null);
const [employees, setEmployees] = React.useState(null);
const [serviceSelected, setServiceSelected] = React.useState(null);
const [employeeSelected, setEmployeeSelected] = React.useState(null);
// For selected Item (services, employees)
const itemSelected = (data, id) => {
const updated = data.map((item) => {
item.toggle = false;
if (item.id === id) {
item.toggle = true;
data === services
? setServiceSelected(item)
: setEmployeeSelected(item);
}
return item;
});
data === services ? setServices(updated) : setEmployees(updated);
};
...
const renderEmployees = ({item}) => {
return (
<TouchableOpacity
onPress={() => itemSelected(employees, item.id)}
delayPressIn={0}
style={styles.employeeContainer}>
<EmployeePattern style={{alignSelf: 'center'}} />
<View style={styles.employeeLogo}>
<Image
source={{uri: item.img}}
style={[styles.imgStyle, {borderRadius: 25}]}
/>
</View>
<View style={{marginTop: 30}}>
<Text style={{textAlign: 'center'}}> {item.name}</Text>
</View>
<View style={{marginTop: 10, alignSelf: 'center'}}>
{item.toggle && <AntDesign name="check" size={25} color="#000" />} // here it's stuck after back and reopen the screen
</View>
</TouchableOpacity>
);
};
React.useEffect(() => {
setServices(VendorProfileData.services);
setEmployees(VendorProfileData.employees);
() => {
setServices(null);
setEmployees(null);
};
}, []);
return (
<View style={styles.container}>
<FlatList
data={services}
renderItem={renderServices}
horizontal
keyExtractor={(item) => item.id.toString()}
contentContainerStyle={{
justifyContent: 'space-between',
flexGrow: 1,
}}
/>
.....
</View>
);
};
Ok so after trying multiple times, i got it
change this
const updated = data.map((item) => {
to this
const updated = data.map((old) => {
let item = {...old};
and please make sure everything is working and we didn't break a thing :),
On your ItemSelected function you are passing the whole employees list, and going through it now thats fine, but when you changing one item inside this list without "recreating it" the reference to that item is still the same "because its an object" meaning that we are modifying the original item, and since we are doing so, the item keeps its old reference, best way to avoid that is to recreate the object,
hope this gives you an idea.

Categories