I am trying to modify a calendar - https://github.com/wix/react-native-calendars so that when I press a day, the background and text colors change for that day. I read that to re-render a component you need to update the state of the parent component, so that is what I am trying:
Parent.js
export default class InitiateRent extends Component {
state = {
....
this.markedDays: {},
someVar: 0
};
constructor() {
super();
this.handler = this.handler.bind(this);
this.markedDays = {};
}
....
handler(e) {
console.log('handler running');
this.setState({
someVar: 123
})
}
<Calendar
handler={this.handler}
markedDates={this.markedDays}
onDayPress={(day)=> {
console.log('selected day', day);
var dateString = `'${day.year}-${day.month}-${day.day}'`
var addDate = {
[dateString]: {
customStyles: {
container: {
backgroundColor: '#6de3dc',
},
text: {
color: 'white',
fontWeight: 'bold'
},
},
}
}
this.markedDays = Object.assign(addDate, this.markedDays);
console.log(this.markedDays);
}}
....
Child.js
pressDay(date) {
this.props.handler();
this._handleDayInteraction(date, this.props.onDayPress);
}
renderDay(day, id) { //GETS CALLED IN CHILD RENDER METHOD VIA AN INTERMEDIARY
....
<DayComp
....
onPress={this.pressDay}
....
}
Everything functions correctly except I don't get the expected result - when I press a date on the calendar, the handler fires, the state changes, and in the console my object looks correct:
Object
'2018-9-23': {customStyles: {container: {backgroundColor: "#6de3dc"}, text: {color: "white", fontWeight: "bold"}}}
'2018-9-26': {customStyles: {container: {backgroundColor: "#6de3dc"}, text: {color: "white", fontWeight: "bold"}}}
'2018-9-28': {customStyles: {container: {backgroundColor: "#6de3dc"}, text: {color: "white", fontWeight: "bold"}}}
'2018-9-29': {customStyles: {container: {backgroundColor: "#6de3dc"}, text: {color: "white", fontWeight: "bold"}}}
But the background of the day on the calendar doesn't change, neither does the text - what do I have to do to get it to re-render (change)?
UPDATE
I created a chain of handlers all the way from the very bottom day
component which represents just a day on the calendar all the way up to the highest order parent view (not App.js, but just below it) and that still did nothing.
UPDATE
The calendar is on a modal, and I don't have any handler on that updating it's state, could that be the problem?
UPDATE
I found this in the docs:
!Disclaimer! Make sure that markedDates param is immutable. If you change markedDates object content but the reference to it does not change calendar update will not be triggered.
What does this mean?
UPDATE
I tried to interpret what that meant with some google searches, does this make this.state.markedDays
immutable?:
const markedDays = this.state.markedDays;
var dateString = `'${day.year}-${day.month}-${day.day}'`;
var addDate = {
[dateString]: {
customStyles: {
container: {
backgroundColor: '#6de3dc',
},
text: {
color: 'white',
fontWeight: 'bold'
},
},
}
}
const markedDaysHolder = {
...markedDays,
...addDate
}
this.state.markedDays = markedDaysHolder;
UPDATE
I put:
componentDidUpdate(prevProps, prevState, snapshot) {
console.log("componentDidUpdate in InitiateRent:", prevProps, prevState, snapshot);
}
The output of the above is:
componentDidUpdate in InitiateRent: (3) (index.bundle, line 761)
{initiateRentMessage: function, modalHeight: 200, modalWidth: 200, handler: function}
{modalVisible: true, message: "Hi, I would like to rent an item from you.", rentButtonBackground: "#6de3dc", someVar: 123, markedDays: Object}
undefined
I can see the state object markedDays
getting bigger with each button press from this output, why isn't the style changing?
In all the relevant components, and I noticed it doesn't fire on the lowest order component, which is the one that needs to change.
I also had this problem, this is what you need to do
This is the flushed out answer for what I was trying to do. I wanted to be able to select and deselect a date by pressing on it (deselecting being the issue after @HaiderAli helped):
All I had to do was:
I added
'selected':
, which needs to be there and this function improves @HaiderAli's answer.To get the deselecting to work, open
node_modules/react-native-calendars/src/calendar/day/custom/index.js
(This is the wrong file for you if you aren't usingmarkingType={'custom'}
prop on the calendar. If you aren't using the prop, editnode_modules/react-native-calendars/src/calendar/day/basic/index.js
). Make this change: