So... how to toggle (mark/unmark) dates when onDayPress was called?
Some like this:
I tried to do this with Object.keys(), push and splice but markedDates haven't a index to manipulate it, so it's very difficult to me to do this.
Date marking
!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.
yarn info react-native-calendars: {latest: '1.16.1'}
yarn info react-native: {latest: '0.51.0'}
Genymotion 2.11.0The same code can to see below:
some imports:
import React, { Component } from 'react'
import moment from 'moment'
import { ScrollView, View, Text } from 'react-native'
import { Calendar } from 'react-native-calendars'
defining constants:
const _format = 'YYYY-MM-DD'
const _today = moment().format(_format)
const _maxDate = moment().add(15, 'days').format(_format)
// It is not possible to reserve some to current day.
let _markedDates = {
[_today]: {disabled: true}
}
onDayPress method called:
const onDaySelect = (day) => {
const selectedDay = moment(day.dateString).format(_format)
const arrDates = Object.keys(_markedDates)
// .map((value, id, ssss) => ({id, value}))
.map((d, i) => {
console.log('d, i: ', _markedDates.indexOf(i))
// const markedDay = moment(d.value).format(_format)
// if (_today !== markedDay) {
// console.log('push: ', markedDay)
// } else if () {
// console.log('splice: ', d, i)
// }
})
// console.log('array dates: ', arrDates)
}
and the calendar component below:
const WixCalendar = (props) => {
return (
<Calendar
// theme={{
// selectedDayBackgroundColor: 'steelblue',
// dotColor: '#00adf5',
// }}
// we use moment.js to give the minimum and maximum dates.
minDate={_today}
maxDate={_maxDate}
// hideArrows={true}
onDayPress={(day) => onDaySelect(day)}
markedDates={_markedDates}
/>
)
}
export default WixCalendar
I've been working to improved this with clean JS:
https://codepen.io/francisrod01/pen/RxKQeO

I clicked in day 31 but the day doesn't marked in the calendar.
You can track the marked dates as state in a stateful React component, here's an example I've based of your expo example:
import React from 'react'
import moment from 'moment' // 2.20.1
import { View } from 'react-native' // 0.0.1
import { Calendar } from 'react-native-calendars' // 1.16.1
const _format = 'YYYY-MM-DD'
const _today = moment().format(_format)
const _maxDate = moment().add(15, 'days').format(_format)
class WixCalendar extends React.Component {
// It is not possible to select some to current day.
initialState = {
[_today]: {disabled: true}
}
constructor() {
super();
this.state = {
_markedDates: this.initialState
}
}
onDaySelect = (day) => {
const _selectedDay = moment(day.dateString).format(_format);
let marked = true;
if (this.state._markedDates[_selectedDay]) {
// Already in marked dates, so reverse current marked state
marked = !this.state._markedDates[_selectedDay].marked;
}
// Create a new object using object property spread since it should be immutable
// Reading: https://davidwalsh.name/merge-objects
const updatedMarkedDates = {...this.state._markedDates, ...{ [_selectedDay]: { marked } } }
// Triggers component to render again, picking up the new state
this.setState({ _markedDates: updatedMarkedDates });
}
render() {
return (
<View style={{flex: 1}}>
<Calendar
// we use moment.js to give the minimum and maximum dates.
minDate={_today}
maxDate={_maxDate}
// hideArrows={true}
onDayPress={this.onDaySelect}
markedDates={this.state._markedDates}
/>
</View>
);
}
}
export default WixCalendar
Thank you @eddiegroves! It's almost that I make here.
The problem now is that the "marked" days doesn't update with style in this marked days.
Is there one way to do that? I think that markedDates is immutable.
Not sure I follow, the example above should be re-rendering and showing the updated marked day automatically. Here's a tweaked example where the dotColor theme is set https://snack.expo.io/r1bMAvN7z
@eddiegroves Thank you for your help from the beginning.
The above example (your second example) doesn't update the marked days.
Well.. I'll from your first example and tell you how it went.
EDIT:
It works for me!! Aleluia!! :1st_place_medal:

Thank you for spread operator tips.
I'm still new to ReactJS and I did not remember that technique.
@francisrod01 If you're new to React it will take a while for it to 'click' but keep at it and things like this will be easier! 馃憤
@eddiegroves What we do it better using the new lifecycle's React?
Discussion: componentWillReceiveProps vs getDerivedStateFromProps:
https://github.com/reactjs/reactjs.org/issues/721#issuecomment-398912285
You Probably Don't Need Derived State
https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html
my version without moment, and I had to change two lines to get it to work (on and off):
const updatedMarkedDates = {...this.state._markedDates, ...{ [_selectedDay]: { 'selected': marked } } }
and
marked = !this.state._markedDates[_selectedDay].selected; //from marked = !this.state._markedDates[_selectedDay].marked
all code:
this.state = {
_markedDates: this.initialState,
....
}
showCalendar = () => {
return (
<Calendar
style={{
borderWidth: 0,
borderRadius: 4,
}}
theme={{
todayTextColor: '#6de3dc',
selectedDayBackgroundColor: '#6de3dc',
selectedDayTextColor: '#ffffff',
}}
markingType={'custom'}
markedDates={this.state._markedDates}
// Initially visible month. Default = Date()
// Minimum date that can be selected, dates before minDate will be grayed out. Default = undefined
minDate={new Date()}
// Maximum date that can be selected, dates after maxDate will be grayed out. Default = undefined
// Handler which gets executed on day press. Default = undefined
onDayPress={day => this.onDayPress(day)}
// Handler which gets executed on day long press. Default = undefined
onDayLongPress={day => {
console.log('selected day', day)
}}
// Month format in calendar title. Formatting values: http://arshaw.com/xdate/#Formatting
monthFormat={'MMM d, yyyy'}
// Handler which gets executed when visible month changes in calendar. Default = undefined
onMonthChange={month => {
console.log('month changed', month)
}}
// Hide month navigation arrows. Default = false
//hideArrows={true}
// Replace default arrows with custom ones (direction can be 'left' or 'right')
//renderArrow={(direction) => (<Arrow />)}
// Do not show days of other months in month page. Default = false
hideExtraDays={true}
// If hideArrows=false and hideExtraDays=false do not switch month when tapping on greyed out
// day from another month that is visible in calendar page. Default = false
//disableMonthChange={true}
// If firstDay=1 week starts from Monday. Note that dayNames and dayNamesShort should still start from Sunday.
firstDay={0}
// Hide day names. Default = false
//hideDayNames={true}
// Show week numbers to the left. Default = false
//showWeekNumbers={true}
// Handler which gets executed when press arrow icon left. It receive a callback can go back month
onPressArrowLeft={substractMonth => substractMonth()}
// Handler which gets executed when press arrow icon left. It receive a callback can go next month
onPressArrowRight={addMonth => addMonth()}
/>
)
}
initialState = {
[new Date()]: {disabled: true}
}
onDayPress = (day) => {
const _selectedDay = day.dateString;
let marked = true;
if (this.state._markedDates[_selectedDay]) {
// Already in marked dates, so reverse current marked state
marked = !this.state._markedDates[_selectedDay].selected;
}
// Create a new object using object property spread since it should be immutable
// Reading: https://davidwalsh.name/merge-objects
const updatedMarkedDates = {...this.state._markedDates, ...{ [_selectedDay]: { 'selected': marked } } }
// Triggers component to render again, picking up the new state
this.setState({ _markedDates: updatedMarkedDates });
}
see my stackoverflow answer for how to make them select and deselect: https://stackoverflow.com/questions/52448375/react-native-rerender-child-component-from-parent-component/52451333#52451333
Does anyone get perf issue while setState?
Not sure I follow, the example above should be re-rendering and showing the updated marked day automatically. Here's a tweaked example where the dotColor theme is set https://snack.expo.io/r1bMAvN7z
Thx so much!!!
Does anyone get perf issue while
setState?
yes! how did you handle that?
Most helpful comment
You can track the marked dates as state in a stateful React component, here's an example I've based of your expo example: