Diogo Alves
Diogo Alves

Reputation: 23

Animation in react native starts in all of the components instead the starting only in the pressed One

I'm new to React Native and as well to Animations in React Native. What I'm trying to do is to fill the checkbox in it's pressed but the way I did made all the checkboxes fill when I press the Touchable Opacity. the 'color' value is defined by this const color = useRef(new Animated.Value(0)).current; I don't know if this is the best way. I searched through the documentation and saw something like this.

    const {
        clean,
        tasks,
        getTasksList,
        edited,
        toogleEdited,
        deleteList,
    } = useContext(listContext);
    const { taskEdited } = useContext(taskContext);
    const [listName, setListName] = useState("");
    const screenHeight = Math.round(Dimensions.get("window").height);
    const colors = useRef(
        Array.from({ length: tasks.length }).fill(new Animated.Value(0))
    );

    async function getListName() {
        setListName(await AsyncStorage.getItem("listName"));
    }
    async function asyncGetTasks() {
        await getTasksList();
    }
    useEffect(() => {
        getListName();
        asyncGetTasks();
    }, [edited, taskEdited]);
    return (
        <View style={styles.container}>
            <StatusBar hidden />
            <View style={styles.buttonsContainer}>
                <TouchableOpacity
                    onPress={() => {
                        clean();
                        navigation.goBack();
                    }}
                >
                    <MaterialIcons name="arrow-back" size={32} />
                </TouchableOpacity>
                <TouchableOpacity
                    onPress={() => {
                        deleteList();
                        clean();
                        navigation.goBack();
                    }}
                >
                    <MaterialIcons name="delete" size={32} color="#bc0000" />
                </TouchableOpacity>
            </View>
            <View style={styles.titleContent}>
                <Text style={styles.titleText}>{listName}</Text>
            </View>
            <ScrollView style={{ height: screenHeight }}>
                {tasks.length > 0 ? (
                    tasks.map((item, index) => (
                        <TouchableOpacity key={index} style={styles.task}>
                            <View style={{ flexDirection: "row" }}>
                                <TouchableOpacity
                                    style={{ alignSelf: "center", marginRight: 8 }}
                                    onPress={() => {
                                        console.log(colors.current[index]);

                                        Animated.timing(colors.current[index], {
                                            toValue: 1,
                                            duration: 1000,
                                        }).start();
                                        toogleEdited();
                                    }}
                                >
                                    <Animated.View
                                        style={{
                                            borderColor: "#000",
                                            borderWidth: 3,
                                            borderRadius: 100,
                                        }}
                                    >
                                        <Animated.View
                                            style={{
                                                backgroundColor: "#000",
                                                height: 22,
                                                width: 22,
                                                borderRadius: 100,
                                                opacity: colors.current[index],
                                            }}
                                            nativeID={item._id}
                                        ></Animated.View>
                                    </Animated.View>
                                </TouchableOpacity>
                                <View>
                                    <Text style={styles.taskText}>{item.title}</Text>
                                </View>
                            </View>

                            <Animated.View
                                style={{
                                    position: "absolute",
                                    alignItems: "center",
                                    alignContent: "center",
                                    opacity: 0.5,
                                    alignSelf: "center",
                                }}
                            >
                                <Text
                                    style={{
                                        color: "#000",
                                        opacity: 0,
                                        fontSize: 32,
                                    }}
                                >
                                    Done!!
                                </Text>
                            </Animated.View>
                        </TouchableOpacity>
                    ))
                ) : (
                    <View style={styles.emptyContent}>
                        <Text style={styles.emptyText}>This list don't have tasks yet</Text>
                    </View>
                )}
            </ScrollView>
            <TouchableOpacity
                style={{
                    position: "absolute",
                    top: screenHeight - 120,
                    right: 28,
                    flexDirection: "row",
                    width: 50,
                    alignSelf: "flex-end",
                }}
                onPress={() => navigation.navigate("NewTask")}
            >
                <Image source={PlusImage} />
            </TouchableOpacity>
        </View>
    );
}

If you don't understand please feel free to ask, my code can be difficult to read but I'm working on that!

edit: I tried some advises that I got here but still does to all and showed more of the code to be more compreensive

Upvotes: 1

Views: 593

Answers (1)

Hagai Harari
Hagai Harari

Reputation: 2877

You store all elements as only one ref, you should make it more dynamic like that

const colors = useRef(Array.from({length: tasks.length} , _ => new Animated.Value(0))).current

use .from({ length }, _ => ...) for creating an array with unique object for each slot in the array (and not same object pointed by all slots)

Now you able to change only one element in onPress

onPress={() => {
         console.log(colors[index]);
         Animated.timing(colors[index], {
         toValue: 1,
         duration: 1000,
         }).start();
    }}

Another notes,

Don't use TouchableOpacity where you don't need onPress functionality, it's blocking it children clickability

For achieving animated behavior in Animated.View, you should chain the animation value with view style prop

<Animated.View
    style={{ ...yourStyle... , 
             opacity: colors[index],
       }}
> 

will create fading animation, while opacity will be 0 / 1 accords animation value

Upvotes: 2

Related Questions