React-native-calendars Show previous and next month instead of arrows using renderArrow function - react-native

Description
Show previous and next month instead of arrows using renderArrow function
Expected Behavior
Show previous month at left side and next month at right side
Observed Behavior
Both side shows previous month
My Code:
<Calendar
onDayPress={(day) => {this.setDay(day)}}
renderArrow={(left,right) => (left? {this.state.previousMonth}: {this.state.nextMonth})}
pastScrollRange={0}
markedDates={{[this.state.selected]: {selected: true, disableTouchEvent: true, selectedColor: '#C7A985'}}}
firstDay={1}
theme={{
selectedDayTextColor: 'white'
}}
/>

There are two things to note in your code.
The renderArrow function contains direction as a parameter which
subsequently contains the values left and right
The renderArrow function accepts JSX attributes
Therefore you need to modify your code in this way
<Calendar
onDayPress={(day) => {this.setDay(day)}}
renderArrow={this._renderArrow}
pastScrollRange={0}
markedDates={{[this.state.selected]: {selected: true, disableTouchEvent: true, selectedColor: '#C7A985'}}}
firstDay={1}
theme={{
selectedDayTextColor: 'white'
}}
/>
and the function as
_renderArrow = (direction) => {
if(direction === 'left') {
return <Text>{this.state.previousMonth}</Text>
} else {
return <Text>{this.state.nextMonth}</Text>
}
}

Related

Updating nested state in React Native when mapping over data

I am mapping over state which displays 3 radio buttons and I only want 1 out of the 3 to be selected at one time and show the selected radio button style - so just a standard behaviour.
The first radio button - isChecked is defaulted to true and I then want to be able to switch the selected styles onPress of the other radio buttons which displays an inner filled circle.
I am getting confused on how to handle the isChecked as true for only the selected Radio Button onPress. I believe I should be using the index of the map to update the state but im unsure on how to go about it.
const [option, setOption] = useState([
{ permission: 'Standard User', isChecked: true },
{ permission: 'Approver', isChecked: false },
{ permission: 'Administrator', isChecked: false },
]);
const RadioButton = ({ checked, onCheck }) => (
<StyledRadioButton onPress={onCheck}>
{checked && <SelectedRadioButton />}
</StyledRadioButton>
);
{option.map(({ isChecked }, i) => (
<RadioButton
onCheck={() =>
setOption(
...prev => {
!prev.isChecked;
},
)
}
checked={isChecked}
/>
))}
Your state is an array of objects which hold a boolean flag. If the user checks a checkbox, then this flag should be set to true while all the others should be set to false. The setter of the state receives an array again, thus we could use the map function again as well as the index argument as you have suggested yourself in your question.
{option.map(({ isChecked }, i) => (
<RadioButton
onCheck={() =>
setOption(
prev => prev.map((opt, index) => ({...opt, isChecked: i === index ? true : false}))
)
}
checked={isChecked}
/>
))}

Implementing react-hook-forms and react-select with radio buttons and multi inputs combo

Ready for a complicated one?
Using react-hook-forms and react-select using creatable (user creates multiple inputs on the fly)
I'm trying to implement a form that uses an option on 4 radio buttons, 2 of which reveal multi inputs (inputs that use react-select where the user can create multiple entries, not a dropdown) and trying to keep track of both the radio inputs and the multi inputs in the final useForm() object. I also need to be able to remove them if the user changes their mind or resets the form in total. Right now, the key values of registrationTypes changes when I change radioTwo and enter inputs. I also don't know how to remove user inputs. I'm using Controller to read the entries (although I've heard if you're using native HTML checkbox input, you have to use Register?) . Here's the code:
import styled from 'styled-components'
import Creatable from 'react-select/creatable'
import { Controller } from 'react-hook-form'
import { ErrorRow } from '../util/FormStyles'
import { FormRulesProps } from '../util/formRuleTypes'
import FormError from './FormError'
const registrationTypes = [
{
label: 'Allow anyone with the link to register',
value: 'radioOne',
},
{
label: 'Allow anyone with this email domain to register:',
value: 'radioTwo',
},
{ label: 'Allow anyone with this code to register:', value: 'radioThree' },
{
label: 'Define eligible users manually through eligibilty file.',
value: 'radioFour',
},
]
const RegistrationEligibilty = () => {
const {
control,
reset,
handleSubmit,
formState: { errors },
} = useForm<any>()
const [selectedRadio, setSelectedRadio] = useState({ regType: '' })
const onSubmit = (data: any) => {
console.log(data)
}
const handleSelected = (value: string) => {
setSelectedRadio({ ...selectedRadio, regType: value })
}
return (
<RegistrationEligibiltyContainer>
<form onSubmit={handleSubmit(onSubmit)}>
<FormRow>
<RadioWrapper>
{registrationTypes.map((rt) => (
<Controller
key={rt.value}
control={control}
name="radio"
render={({ field: { onChange, value } }: any) => (
<RadioGroup
// #ts-ignore
value={value}
onChange={(e: any) =>
onChange(e.target.value, handleSelected(rt.value))
}
>
<Radio
name={rt.value}
type="radio"
value={rt.value}
checked={selectedRadio.regType === rt.value}
/>
<TextRow
text={rt.label}
style={{ paddingLeft: '10px' }}
/>
{selectedRadio.regType === 'radioTwo' &&
rt.value === 'radioTwo' && (
<FormRow>
<div style={{ width: '90%' }}>
<Controller
name={rt.value}
control={control}
render={({ field }) => (
<Creatable
{...field}
isMulti
options={field.value}
value={field.value}
placeholder="Select domains"
/>
)}
/>
</div>
</FormRow>
)}
{selectedRadio.regType === 'radioThree' &&
rt.value === 'radioThree' && (
<FormRow>
<div style={{ width: '90%' }}>
<Controller
name={rt.value}
control={control}
render={({ field }) => (
<Creatable
{...field}
isMulti
options={field.value}
value={field.value}
placeholder="Select codes"
/>
)}
/>
</div>
</FormRow>
)}
</RadioGroup>
)}
/>
))}
</RadioWrapper>
</FormRow>
</FormContent>
</form>
</RegistrationEligibiltyContainer>
)
}
export default RegistrationEligibilty
The result looks like this:
https://imgur.com/a/6oGhqRb
I also need to be able to remove them if the user changes their mind or resets the form in total
If the component is unmounted, the value of the component is not included in the result. Make sure your Creatable is unmounted when the relevant radio is not selected

React Native conditionally setting state

I have an array of "favorite" listings per user. I want to set a state variable depending on if it is rendering a favorite item or a regular (non-favorite) item. This is a little heart icon that is either filled or unfilled. It is incorrectly setting the state on first render. Correctly sets it after refresh.. I'm doing something wrong and have tried many things to no avail so if someone could just look at this code and tell me if you see any glaring flaws. If not then I will look elsewhere for the problem.
Behavior when app loads: I am doing console.log just after the state is set to show whether it's a favorite or not, and the contents of the favorite state variable (an image url, but in the console it shows it as either 21 for non-fav, or 22 for a fav). I can see that it is correctly pulling the array of favorites, and correctly identifying those that are and are not favorited (1 means its a favorite). It is however not setting the state variable correctly. Furthermore, it IS setting it correctly for only some of the listings. Currently I have all listings marked as a favorite, and it only messes up the first 10. After that they all set right. MORE bizarre, is upon refreshing the screen, it correctly sets all of them.
MainHeader.js (pulling data from db, setting initial array of favorite listings, and passing it to the messagesScreen component)
const [favsArray, setFavsArray] = useState("");
useEffect(() => {
lookupUser()
.then((snapshot) => {
if (snapshot.hasChildren()) {
snapshot.forEach(function(childSnapshot) {
let favs = childSnapshot.child("favorites").val();
setFavsArray(favs);
})
}
})
.catch((error) => {console.error('Error:', error)});
}, []);
return (
<NavigationContainer>
<View style={styles.headerContainer}>
<Image
style={styles.image}
source={require("../assets/newheader4.png")}
/>
</View>
<Tab.Navigator
tabBarOptions={{
activeTintColor: "blue",
inactiveTintColor: "black",
style: {},
tabStyle: {
width: "auto",
backgroundColor: "#e0d5f3",
borderTopWidth: 3,
borderBottomWidth: 3,
borderRightColor: "gray",
},
labelStyle: {
fontSize: 14,
fontWeight: "bold",
},
scrollEnabled: true,
}}
>
<Tab.Screen name="All Deals" children={()=><MessagesScreen favsArray={favsArray} setFavsArray={setFavsArray}/>} />
</Tab.Navigator>
</NavigationContainer>
MessagesScreen, receives favsArray and renders a FlatList with component Card which it feeds favsArray to.
<FlatList
data={messagesShow}
keyExtractor={(messagesShow) => messagesShow.id.toString()}
renderItem={({ item }) => (
<Card
price={item.currentPrice}
title={item.title}
image={item.image}
posted={item.postedDate}
discAmount={item.discountAmount}
discType={item.discType}
expiration={item.expiration}
promoCode={item.promoCode}
affLink={item.amzLink}
indexStore={item.indexStore}
store={item.store}
favsArray = {favsArray}
/>
)}
ItemSeparatorComponent={ListItemSeparator}
contentContainerStyle={styles.messagesList}
refreshing={refreshing}
onRefresh={() =>
db.ref('deals').once('value', (snapshot) =>{
let testData = [];
snapshot.forEach((child)=>{
// if (child.val().hasOwnProperty('title')){
testData.push({
id: child.key,
title: child.val().hasOwnProperty('title') ? child.val().title : 'NA',
currentPrice: child.val().price,
discountAmount: child.val().discAmt,
discType: child.val().discType,
promoCode: child.val().promoCode,
expiration: child.val().expDate,
postedDate: child.val().postDate,
image: { uri: child.val().imageLink},
amzLink: child.val().affLink,
category: child.val().category,
indexStore: child.val().indexStore,
store: child.val().store
})
// }
checkMessages(testData);
})
})
.then()
.catch((error) => {console.error('Error:', error)})
}
/>
Card component, this is in a FlatList where favsArray is passed as a prop (correctly verified by console), along with the individual listing data. If it finds the listing in the fav array, it should set to HeartFilled (1), if not set to HeartEmpty (0).
let test = [];
test = favsArray.split(',');
let isFav = 0;
let found = test.find(function (element) {
return element == indexStore;
});
if (found != undefined){
isFav = 1;
}
const [heartFilled, setHeartFilled] = useState( isFav == 1 ? require('../assets/heartFilled.png') : require('../assets/heartEmpty.png'));
console.log(isFav + ' ' + heartFilled);
Looking at my console, you can see it correctly shows each listing as a favorite, but for the first 10 listings it sets the state to the wrong image (21, shown in red). These should all be 22.

MUIDataTable I want to hide checkbox but also i want row data when i click on rows

i am doing this but onRowClick is not working
<MUIDataTable
data={tableData}
columns={tableCols}
options={{
search: true,
fixedHeader: true,
selectableRows: 'none',
selectableRowsOnClick: true,
displayRowCheckbox:false,
onRowClick:this.getRow,
customToolbarSelect: () => {},
}}
/>
is there any option to hide check also and geting row data also
You can hide this if you pass selectableRows: false in options props.
for more details follow the documentation.
<MUIDataTable
title={"Employee List"}
data={data}
columns={columns}
options={{
selectableRows: false // <===== will turn off checkboxes in rows
}}
/>
Try adding this:-
selectableRows: "multiple",
selectableRowsHideCheckboxes: true,
selectableRowsOnClick: true,

How to set date on scrolling the Week Calendar in react-native-calendars package

I am trying to use WeekCalendar from react-native-calendars package. I am able to view the WeekCalendar and scroll it. However, I want that on horizontal scroll - the currentDate should be updated to date in that current week and should be updated on the UI. How do I go about this?
I was able to find a solution for onclick but I want on scrolling the current date should be a date from that current week.
<WeekCalendar
firstDay={1}
current={selectedDateOfTheWeek}
onDayPress={(day, localDay) => {
changeSelectedDateFromCalendar(day.dateString, false);
}}
hideExtraDays={false}
pastScrollRange={24}
futureScrollRange={24}
markedDates={{
[selectedDateOfTheWeek]: {
selected: true,
selectedColor: "#8660ce"
}
}}
/>
selectedDateOfTheWeek stores the date in 'YYYY-MM-DD' format. I am using Redux to manage the state.
wrap your week calendar with <CalendarProvide and use onDateChanged event
<CalendarProvider
date={this.state.selectedDate.dateString}
onDateChanged={this.onDateChanged}
markedDates={{
...this.state.markedDates,
[this.state.selectedDate.dateString]: {
selected: true,
},
}}
>
<WeekCalendar
testID={testIDs.weekCalendar.CONTAINER}
hideDayNames={true}
firstDay={1}
dayComponent={this.renderDateWeek}
theme={calendarThemes}
calendarWidth={screenWidth}
allowShadow={false}
markedDates={{
...this.state.markedDates,
[this.state.selectedDate.dateString]: {
selected: true,
},
}}
pastScrollRange={(new Date().getFullYear() - 1900) * 12}
futureScrollRange={(2099 - new Date().getFullYear()) * 12}
style={[styles.calendar, { paddingBottom: 20, paddingLeft: 0, paddingRight: 0 }]}
onDayPress={(date) => this.changeDate(date.dateString)}
/>
</CalendarProvider>