react-nativedom-manipulationonpresspressable

How to get React Native Pressable onPress to manipulate target


I have an array filled with the letters of the alphabet that I have turned into Pressable components. My goal is to change the color of the letter clicked depending on some state. React Native's Pressable onPress prop accepts a function with an event argument. Sadly you can't simply do the classic event.target.style.color in order to manipulate the target like you can in vanilla js. This is what I have tried so far:

const onPressLetter = (evt) => {
    let targetStyle = evt._dispatchInstances.memoizedProps.children[0].props.style;

    shadeLetter ? targetStyle.color = 'rgba(0, 0, 0, 0.5)' : targetStyle.color = 'green';
}

The color change isn't taking place when clicked. Console logging targetStyle before and after where we change the color even reflects that the style object has changed. What am I doing wrong? How can i accomplish this in react native??

Keep in mind I dont want to use the style prop for Pressable because I want the color change to stay after click


Solution

  • Induce a bijection between letters and boolean states, which you can keep in a single state array. Provide the onPressLetter function with an index and toggle the corresponding state.

    Here is a minimal example using map. In a real application, I would use a FlatList. The workflow stays the same.

    const alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    
    const Screen = (props) => {
        const [pressedLetters, setPressedLetters] = useState(alphabet.map(letter => false))
        
        function onPressLetter(i) {
            setPressedLetters(prev => prev.map((item, index) => index === i ? !item : item))
        }
    
        return (
                alphabet.map((item, index) => {
                    return <Pressable onPress={() => onPressLetter(index)}>
                         <Text style={ {color: pressedLetters[index] ? 'green' : 'rgba(0, 0, 0, 0.5)'}}>{item}</Text>
                    </Pressable>
                })
        )
    }