Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native onFocus and onBlur TouchableOpacity

I am using react natives Touchable Opacity to animate/give an effect to the box I am hovering over. I am developing an app for android TV. I wanted to make a hover effect similar to the default android tv home screen (When navigating, on focus, the cards enlarge and on blur the cards get smaller). I am also using map to iterate over many items. Here is what I have got so far.


import React, { Component } from 'react';
import { StyleSheet, View, TouchableOpacity } from 'react-native';

export default class TV extends Component {

    constructor(props) {
        super(props);
        this.state = {
            bgColor: 'gray',
            entries: [
                {
                    "albumId": 1,
                    "id": 1,
                    "title": "accusamus beatae ad facilis cum similique qui sunt",
                    "url": "https://via.placeholder.com/600/92c952",
                    "thumbnailUrl": "https://via.placeholder.com/150/92c952"
                },
                {
                    "albumId": 1,
                    "id": 2,
                    "title": "reprehenderit est deserunt velit ipsam",
                    "url": "https://via.placeholder.com/600/771796",
                    "thumbnailUrl": "https://via.placeholder.com/150/771796"
                }]
        }
    }


        render () {
        return (
            <View style={styles.thumbnailContainer}>
                {
                    this.state.entries.map((e, index) => {
                        return(

                                <TouchableOpacity onPress={()=>null} onFocus={()=>this.setState({bgColor: 'red'})} onBlur={()=>this.setState({bgColor: 'gray'})}>
                                    <View style={styles.thumbnailWrapper}></View>
                                </TouchableOpacity>

                            )
                    })
                }
            </View>
        );
    }
}

const styles = StyleSheet.create({
    thumbnailContainer: {
      flex: 1,
      flexDirection:'row',
      flexWrap:'wrap'
    },
    thumbnailWrapper: {
        backgroundColor: 'gray',
        width: 50,
        height: 50
    }
})

I am currently testing with background color only. Not sure how I can get the style background color to change. It gives me a undefined is not an object (evaluating this.state) if I do backgroundColor: this.state.bgColor.

So How can I animate the "Cards" or in this case just plain views when focused on and blurred on.

Edit:

Solved the problem. Hope someone finds this useful. I am not sure if this is the right way to do this. But I just created a state which stores the current index of the hover. If the current index of the mapped index is same, then background color should be red. Here is the full code:


import React, { Component } from 'react';
import { StyleSheet, View, TouchableOpacity, Text } from 'react-native';

export default class TV extends Component {

    constructor(props) {
        super(props);
        this.state = {
            bgColor: 'red',
            index: 0,
            entries: [
                {
                    "albumId": 1,
                    "id": 1,
                    "title": "accusamus beatae ad facilis cum similique qui sunt",
                    "url": "https://via.placeholder.com/600/92c952",
                    "thumbnailUrl": "https://via.placeholder.com/150/92c952"
                },
                {
                    "albumId": 1,
                    "id": 2,
                    "title": "reprehenderit est deserunt velit ipsam",
                    "url": "https://via.placeholder.com/600/771796",
                    "thumbnailUrl": "https://via.placeholder.com/150/771796"
                }]
        }
    }

    render() {
        return (
            <View style={styles.thumbnailContainer}>
                {
                    this.state.entries.map((e, index) => {
                        return (
                            <TouchableOpacity
                                key={e.id}
                                onFocus={() => this.setState({ bgColor: 'red', index: index })}
                                onBlur={() => this.setState({ bgColor: 'gray' })}
                            >
                                <Text style={[styles.thumbnailWrapper, this.state.index == index ? { backgroundColor: this.state.bgColor } : { backgroundColor: 'gray' }]}>{e.title}</Text>
                            </TouchableOpacity>

                        )
                    })
                }
            </View>
        );
    }
}

const styles = StyleSheet.create({
    thumbnailContainer: {
        flex: 1,
        alignContent: 'center',
        justifyContent: 'center'
    },
    thumbnailWrapper: {
        width: 350,
        height: 50
    }
})


like image 476
Mohamed Ahmed Avatar asked Sep 06 '26 03:09

Mohamed Ahmed


1 Answers

you are trying to pass state to backgroundColor outside the main class, notice const styles = StyleSheet.create() is outside the export default class TV extends Component{} states can only passed inside the class

try this:

import React, { Component } from 'react';
import { StyleSheet, View, TouchableOpacity, Text } from 'react-native';

export default class TV extends Component {

  constructor(props) {
    super(props);
    this.state = {
      bgColor: 'gray',
      entries: [
        {
          "albumId": 1,
          "id": 1,
          "title": "accusamus beatae ad facilis cum similique qui sunt",
          "url": "https://via.placeholder.com/600/92c952",
          "thumbnailUrl": "https://via.placeholder.com/150/92c952"
        },
        {
          "albumId": 1,
          "id": 2,
          "title": "reprehenderit est deserunt velit ipsam",
          "url": "https://via.placeholder.com/600/771796",
          "thumbnailUrl": "https://via.placeholder.com/150/771796"
        }]
    }
  }

  render() {
    return (
      <View style={[styles.thumbnailContainer, { backgroundColor: this.state.bgColor }]}>
        {
          this.state.entries.map((e, index) => {
            return (
              <TouchableOpacity
                key={e.id}
                onFocus={() => this.setState({ bgColor: 'red' })}
                onBlur={() => this.setState({ bgColor: 'gray' })}
              >
                <Text style={styles.thumbnailWrapper}>{e.title}</Text>
              </TouchableOpacity>

            )
          })
        }
      </View>
    );
  }
}

const styles = StyleSheet.create({
  thumbnailContainer: {
    flex: 1,
    alignContent: 'center',
    justifyContent: 'center'
  },
  thumbnailWrapper: {
    width: 350,
    height: 50
  }
})

this should solve your undefined error

like image 188
Areeb Vohra Avatar answered Sep 07 '26 18:09

Areeb Vohra



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!