ghDev
ghDev

Reputation: 180

Changing style of specific component returned from map function onClick

I am trying to change the style of individual TouchableOpacity components that have been returned from a map function.

Here is the component:

Example = ({ props }) => {  
    return (
        <View>
            {props.listExample.map(({ id }) => {
                return (
                    <React.Fragment key={id}>
                        <TouchableOpacity
                            style={styles.button}
                            onPress={() => console.log(id)}>
                            <Image source={require('example.jpg')} />
                        </TouchableOpacity>
                    </React.Fragment>
                );
            })}
        </View>
    );
};

Let TouchableOpacity = TO.

The map function returns about 30 TOs with unique IDs. When I click the TOs, I can see their unique ID in the console log. I want to know how I can modify the style of an individual TO.

Here is my render function which uses the functional component Example.

render() {
    return (
        <View style={styles.body}>
            <ScrollView>
                <View style={styles.column}>
                    <this.Example props={{ listExample: this.getList() }} />
                </View>
            </ScrollView>
        </View>
    );
}

What I have tried:

referencing this stackoverflow post, I tried to create a function which changed the style of the TO when it is clicked. But the result of this changed all the TOs in the UI since of the way it is mapped. I tried something like the following.

Example = ({ props }) => {  
    return (
        <View>
            {props.listExample.map(({ id }) => {
                let buttonStyle = this.state.pressed ? styles.button : styles.buttonClicked
                return (
                    <React.Fragment key={id}>
                        <TouchableOpacity
                            style={buttonStyle}
                            onPress={() => console.log(id)}>
                            <Image source={require('example.jpg')} />
                        </TouchableOpacity>
                    </React.Fragment>
                );
            })}
        </View>
    );
};

But as previously stated, this changed all of the Touchable Opacitys. Is there a way to only change one?

Thanks

Edit - to show entire class

class Page extends Component {

    constructor(props) {
        super(props)
    }

    MyButton = ({ onButtonPressed = () => {} }) => {
        const [isPressed, setIsPressed] = useState(false);
        const onPressed = () => {
          setIsPressed(!isPressed);
          onButtonPressed();
       }
       return (<TouchableOpacity style={isPressed ? styles.pressedButton: styles.button}
                   onPress={onPressed}>
                   <Image source={require('example.jpg')} />
                </TouchableOpacity>
       );
    }

    Example = ({ props }) => {
        return (
            <View>
                {props.listExample.map(({ id }) => {
                    return (
                        <MyButton key={id}/>
                    );
                })}
            </View>
        );
    };

    render() {
        return (
            <View style={styles.body}>
                <ScrollView>
                    <View style={styles.column}>
                        <this.Example props={{ listExample: this.getList()}} />
                    </View>
                </ScrollView>
            </View>
        );
    }

}

Upvotes: 1

Views: 2162

Answers (1)

duc mai
duc mai

Reputation: 1422

It is easier to separate the component inside map to a separate component and then handle style changes on press there

const MyButton = ({ onButtonPressed = () => {} }) => {
    const [isPressed, setIsPressed] = useState(false);
    const onPressed = () => {
      setIsPressed(!isPressed);
      onButtonPressed();
   }
   return (<TouchableOpacity style={isPressed ? styles.pressedButton: styles.button}
               onPress={onPressed}>
               <Image source={require('example.jpg')} />
            </TouchableOpacity>
   )
}

so you can use in the map like this

Example = ({ props }) => {  
    return (
        <View>
            {props.listExample.map(({ id }) => {
                return (
                    <MyButton key={id} />
                );
            })}
        </View>
    );
};

Upvotes: 1

Related Questions