React Native Calendars : How to change the background color of only one item using Redux

2.3k Views Asked by At

I'm trying to change the background of only one item in this agenda but with my code, when I click on an item, it changes the background color of all of them and not just the one I clicked : Before clicked after clicked. I want also to store the value of my state in redux so that I can display the screen elsewhere in my application while conserving the green color.

Here is my code from my calendar:

import React, {useState, useCallback, useEffect} from 'react';
import {
    Text,
    View,
    TouchableOpacity,
} from 'react-native';
import { useSelector, useDispatch } from "react-redux";
import { Avatar, Card } from 'react-native-paper';
import {Agenda} from "react-native-calendars";
import { toggleActive} from "../store/actions/calendar";
import * as firebase from "firebase";

const activeItemText = 'Réservé';
const activeItemStyles = {
    backgroundColor: 'lightgreen',
    backgroundColor2: 'white',
};
const inactiveItemText = 'Disponible';
const inactiveItemStyles = {
    backgroundColorPrimary: 'white',
    backgroundColorSecondary: 'white',
};

const timeToString = (time) => {
    const date = new Date(time);
    return date.toISOString().split('T')[0];
};

const CalendarItem = ({item, firstItemInDay}) => {
  //  const [active, setActive] = useState(false);
    const dispatch = useDispatch();

    const active = useSelector(state => state.calendar.active);

    const toggleActiveHandler = useCallback(() => {
        dispatch(toggleActive())
    }, [dispatch]);




   // const [active1, setActive1] =  React.useState(false);

  //  console.log(active);
   /* const changeColor = () => {
       setActive(!active)
    };
    */

    return (
        <TouchableOpacity
            style={{marginTop: 17, marginRight: 10}}
            onPress={toggleActiveHandler}>
            <Card style={active ? activeItemStyles : inactiveItemStyles}>
                <Card.Content>
                    <View
                        style={{
                            flexDirection: 'row',
                            justifyContent: 'space-between',
                            alignItems: 'center',
                        }}>
                        <Text>{active ? activeItemText : inactiveItemText}</Text>
                        <Avatar.Text label="J" />
                    </View>
                </Card.Content>
            </Card>
        </TouchableOpacity>
    );
};

const renderItem = (item, firstItemInDay) => {
    return <CalendarItem item={item} firstItemInDay={firstItemInDay} />;
};

const calendarScreen = () => {
    const [items, setItems] = useState({});

    const loadItems = (day) => {
        setTimeout(() => {
            for (let i = -15; i < 85; i++) {
                const time = day.timestamp + i * 24 * 60 * 60 * 1000;
                const strTime = timeToString(time);

                if (!items[strTime]) {
                    items[strTime] = [];
                    const numItems = 1;
                    for (let j = 0; j < numItems; j++) {
                        items[strTime].push({
                            name: inactiveItemStyles.texte,
                            height: Math.max(50, Math.floor(Math.random() * 150)),
                        });
                    }
                }
            }
            const newItems = {};
            Object.keys(items).forEach((key) => {
                newItems[key] = items[key];
            });
            setItems(newItems);
        }, 1000);
    };

    return (
        <View style={{flex: 1}}>
            <Agenda
                items={items}
                loadItemsForMonth={loadItems}
                selected={'2020-09-23'}
                renderItem={renderItem}
            />
        </View>
    );
};

export default calendarScreen;

Here is my reducer :

import { TOGGLE_ACTIVE } from "../actions/calendar";


const initialState = {
    active: false
};


const calendarReducer = (state = initialState, action) => {
    switch (action.type) {
        case TOGGLE_ACTIVE :
            console.log(state);
            console.log(!!state);
            return {
                active: !!state};
        default:
            return state
    }
};

export default calendarReducer;

And here is my action :

export const TOGGLE_ACTIVE = 'TOGGLE_ACTIVE';

export const toggleActive = () => {
    return    { type: TOGGLE_ACTIVE }
};

Thanks a lot in advance for your help !

1

There are 1 best solutions below

5
On

You are just saving active state, that's why its changing background for all. Cause, it can't differentiate for which you have changed the state . So, keep some unique data from the item that you have clicked to compare it with others. If the redux data match change background otherwise not.