The below code changes style to itemStyles.listItemPressed to all the elements in the Item loop. I need to have only one element change the style on pressing the container. Down below i have my second way of tryng to do that. But in the second try the pressed styles apply and stay there after i let go of my finger. I need the style to change back to default after i dont press on the screen.
const [isPressed, setIsPressed] = React.useState(false);
const [selectBtn, setSelectBtn] = React.useState(null);
function onPressIn() {
setIsPressed(true);
}
function onPressOut() {
setIsPressed(false);
}
<View>
{options.map((option) => (
<Pressable
onPress={onPress}
onPressIn={onPressIn}
onPressOut={onPressOut}
style={[
itemStyles.listItem,
isPressed && itemStyles.listItemPressed,
]}
>
<Item
checked={option.value === value}
key={option.value}
label={option.label}
disabled={disabled}
onPress={() => onChange(option.value)}
/>
</Pressable>
))}
</View>
Second try
return (
<View style={style}>
<View>
{options.map((option, index) => (
<Pressable
style={[
itemStyles.listItem,
{ backgroundColor: selectBtn === index ? 'red' : 'gray' },
]}
onPressIn={() => {
setSelectBtn(index);
}}
onPressOut={null}
onPress={onPress}
>
<Item
checked={option.value === value}
key={option.value}
label={option.label}
disabled={disabled}
onPress={() => onChange(option.value)}
/>
</Pressable>
))}
</View>
</View>
);
}
My options array
options={[
{ label: "Value", value: "value" },
{ label: "Value", value: "value2" },
{ label: "Value", value: "value3" },
{ label: "Value", value: "value4" },
{ label: "Value", value: "value5" },
]}
CodePudding user response:
You could use some other logic for this.
But what have done with a similar problem where. I had to change color of an element in a loop on hover.
I made a separate component for the item inside the loop on which i had to apply changes.
Then in that separate component i had a state like isPressed
. Now what it does is that each element in the loop have its own personal state for isPressed so i can check it for each individual item without affecting other elements in the loop.
For Example: App.js
function App(){
return <div>
{someArray.map((item)=><Component ...props... />)}
</div>
}
Component.js
function Component(){
const [isPressed, setIsPressed] = useState(false);
return
<someTag onClick={()=>setIsPressed(true)} style={{color:isPressed ? 'blue' : 'red'}} >....</somTag>
}
You can also handle function on click in App.js then you have to pass function as a prop to Component and onClick in Component it will call props.sentFunction ...
CodePudding user response:
Im assuming you know which elements index you want to change style when onPressed
Hey you can do something like this :
CodePudding user response:
I'd approach this problem that have elements with multiple properties and states by using useReducer
: https://snack.expo.dev/@zvona/state-of-multiple
Here's the full code from the snack of handling state through useReducer:
import { useState, useReducer } from 'react';
import { Text, Pressable, View, StyleSheet } from 'react-native';
const options = [{ value: 'first' }, { value: 'second' }, { value: 'third' }];
const initialState = { ...options };
const App = () => {
const selectedReducer = (state, { type, index }) => {
const { selected, pressed } = state[index];
const newState = { ...state };
switch (type) {
case 'pressIn':
newState[index].pressed = true;
break;
case 'pressOut':
newState[index].pressed = false;
break;
case 'press':
newState[index].selected = !selected;
break;
default:
console.warn('invalid type');
break;
}
return newState;
};
const [state, dispatch] = useReducer(selectedReducer, initialState);
const getStyling = (index) => [
styles.pressableStyle,
state[index].selected && styles.listItemSelected,
state[index].pressed && styles.listItemPressed,
];
return (
<View style={styles.container}>
<View>
{options.map((option, index) => (
<Pressable
onPressIn={() => dispatch({ type: 'pressIn', index })}
onPressOut={() => dispatch({ type: 'pressOut', index })}
onPress={() => dispatch({ type: 'press', index })}
style={getStyling(index)}>
<Text>{option.value}</Text>
</Pressable>
))}
</View>{' '}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 8,
},
pressableStyle: {
backgroundColor: 'white',
padding: 10,
marginBottom: 10,
borderColor: 'black',
borderWidth: 1,
},
listItemPressed: {
backgroundColor: 'blue',
},
listItemSelected: {
backgroundColor: 'green',
},
});
export default App;