Search code examples
javascriptandroidreact-nativevariablestouchableopacity

Can't Find Variable: setState


I'm trying to make a toggle button that changes icon and the icon color when clicked, i'm following a tutorial but ran into this problem.

Ive tried changing things around, messing with it but I keep getting the same error: "Cannot Find Variable: setState"

variable Error

The code thats causing the problem:

import { View, Text, StyleSheet ,Image, TouchableOpacity } from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import { Caption } from "react-native-paper"

const FlagSection = (props) => {

    const state = {
        heartIcon: "ios-heart-outline",
        liked: false
    }

    const toggleLike = () => {
        setState({
            liked: !state.liked
        })

        if(state.heartIcon){
            setState({
                heartIcon: "ios-heart"
            })
        }else{
            setState({
                heartIcon: "ios-heart-outline"
            })
        }
    }

    return (
        <View style={ styles.container }>
            <View style={ {flex:1} }>
            
                <View style= {styles.flagInfo}>
                    <View style= {styles.imageContent}>
                        <Image
                            source={ props.detail.flag }
                            size={60}
                        />

                        <View style= {styles.currencyContent}>
                            <Text> {props.detail.abbreviation} </Text>
                            <Caption style={ styles.caption }> {props.detail.name} </Caption>
                        </View>

                        <View style= {styles.likeButton}>
                            <TouchableOpacity onPress={ toggleLike }>
                                <Icon name={state.heartIcon} size={40} style={{color: state.heartIcon === "ios-heart-outline" ? "black" : "red"}}/>
                            </TouchableOpacity>
                        </View>
                    </View>
                </View>
            
            </View>
        </View>
    )
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
    flagInfo: {
        paddingLeft: 20,
        borderWidth: 5,
    },
    imageContent: {
        flexDirection: "row",
        marginTop: "3%",
    },
    currencyContent: {
        marginLeft: "3%",
        flexDirection: "column"
    },
    caption: {
        fontSize: 16,
        paddingTop: "3%",
        lineHeight: 14,
    },
    likeButton: {
        flexDirection: "row",
        justifyContent: "flex-end",
        marginLeft: "auto"
    }
});

export default FlagSection;```

Solution

  • You need to define the initial state with useState in a functional component:

    const [state, setState] = useState({
        heartIcon: "ios-heart-outline",
        liked: false
    });
    

    Then, to update individual properties without losing the other one, spread the existing state:

    setState({
        ...state,
        liked: !state.liked
    })
    

    But I'd highly recommend separating out the properties into different stateful variables instead:

    const [heartIcon, setHeartIcon] = useState('ios-heart-outline');
    const [liked, setLiked] = useState(false);
    

    Then you'd just need to use, for example, setLiked(!liked) instead having to also manage the copying over of the previous values in the same state variable.