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 !
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.