I have an issue: thre is a list of users, and I want to add appointment to any user, so on user screen a PlusButton sending user on the add appointment screen (the PlusButton rendered from headerRight of the user screen). BUT I dont know how to pass to AddAppointmentScreen users id, because link to screen not via button, its via react-navigation v5.
here is a link to my project on github
App.js
const HeaderRight = ({ navigation, target }) => {
return (
<Button transparent onPress={() => navigation.navigate(target)}>
<Icon name='plus' type='Entypo' style={{ fontSize: 26 }} />
</Button>
)
}
<Stack.Screen
name='Patient'
component={PatientScreen}
options={{
title: 'Карта пациента',
headerTintColor: '#2A86FF',
headerTitleAlign: 'center',
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 20,
},
headerBackTitleVisible: false,
headerRight: () => <HeaderRight navigation={navigation} target={'AddAppointment'} />,
}}
/>
AddAppointmentScreen.js
import React, { useState } from 'react'
import { Keyboard } from 'react-native'
import { Container, Content, Form, Item, Input, Label, Icon, Text, Button } from 'native-base'
import DateTimePicker from '#react-native-community/datetimepicker'
import styled from 'styled-components/native'
import { appointmentsApi } from '../utils/api'
const AddAppointmentScreen = ({ route, navigation }) => {
const [values, setValues] = useState({ patientId: route.params?.patientId._id ?? 'defaultValue' })
const [date, setDate] = useState(new Date())
const [mode, setMode] = useState('date')
const [show, setShow] = useState(false)
console.log(values.patientId)
//I need to get patientId in this screen to create appointment to THIS user with its ID
const setFieldValue = (name, value) => {
setValues({
...values,
[name]: value,
})
}
const handleChange = (name, e) => {
const text = e.nativeEvent.text
setFieldValue(name, text)
}
const submitHandler = () => {
appointmentsApi
.add(values)
.then(() => {
navigation.navigate('Patient')
})
.catch((e) => {
alert(e)
})
/* alert(JSON.stringify(values)) */
}
const formatDate = (date) => {
var d = new Date(date),
month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = d.getFullYear()
if (month.length < 2) month = '0' + month
if (day.length < 2) day = '0' + day
return [year, month, day].join('-')
}
const onChange = (event, selectedDate) => {
Keyboard.dismiss()
const currentDate = selectedDate || date
const date = formatDate(currentDate)
const time = currentDate.toTimeString().split(' ')[0].slice(0, 5)
setShow(Platform.OS === 'ios')
setDate(currentDate)
setValues({
...values,
['date']: date,
['time']: time,
})
}
const showMode = (currentMode) => {
show ? setShow(false) : setShow(true)
setMode(currentMode)
}
const showDatepicker = () => {
Keyboard.dismiss()
showMode('datetime')
}
return (
<Container>
<Content style={{ paddingLeft: 20, paddingRight: 20 }}>
<Form>
<Item picker style={{ borderWidth: 0 }} /* floatingLabel */>
<Input
onChange={handleChange.bind(this, 'dentNumber')}
value={values.dentNumber}
keyboardType='number-pad'
clearButtonMode='while-editing'
placeholder='* Номер зуба'
/>
</Item>
<Item picker>
<Input
onChange={handleChange.bind(this, 'diagnosis')}
value={values.diagnosis}
clearButtonMode='while-editing'
placeholder='* Диагноз'
/>
</Item>
<Item picker>
<Input
onChange={handleChange.bind(this, 'description')}
value={values.description}
multiline
clearButtonMode='while-editing'
placeholder='Подробное описание или заметка'
style={{ paddingTop: 15, paddingBottom: 15 }}
/>
</Item>
<Item picker>
<Input
onChange={handleChange.bind(this, 'price')}
value={values.price}
keyboardType='number-pad'
clearButtonMode='while-editing'
placeholder='* Цена'
/>
</Item>
<ButtonRN onPress={showDatepicker}>
<Text style={{ fontSize: 18, fontWeight: '400' }}>
Дата: {formatDate(date)}, время: {date.toTimeString().split(' ')[0].slice(0, 5)}
</Text>
</ButtonRN>
{show && (
<DateTimePicker
timeZoneOffsetInSeconds={21600}
minimumDate={new Date()}
value={date}
mode={mode}
is24Hour={true}
display='default'
locale='ru-RU'
minuteInterval={10}
onChange={onChange}
/>
)}
<ButtonView>
<Button
onPress={submitHandler}
rounded
block
iconLeft
style={{ backgroundColor: '#84D269' }}
>
<Icon type='Entypo' name='plus' style={{ color: '#fff' }} />
<Text style={{ color: '#fff' }}>Добавить прием</Text>
</Button>
</ButtonView>
<Label style={{ marginTop: 10, fontSize: 16 }}>
Поля помеченные звездочкой <TomatoText>*</TomatoText> обязательны для заполнения
</Label>
</Form>
</Content>
</Container>
)
}
const ButtonRN = styled.TouchableOpacity({
paddingTop: 15,
paddingLeft: 5,
})
const ButtonView = styled.View({
marginTop: 15,
})
const TomatoText = styled.Text({
color: 'tomato',
})
export default AddAppointmentScreen
I have not gone through your code but I can tell you how can you pass params to next screen as per your heading.
toNavigate = (user) => {
this.setState({ isLoading: false },
() => { this.props.navigation.push('Main', { userData: user }) })
//I am sending user into userData to my Main screen
}
And I am receive it like
render(){
user = this.props.route.params.userData;
}
If any issue let me know.
Hope it helps!!!
This can be done using the useNavigation hook as you are inside the Navigation Container.
import { NavigationContainer, useNavigation } from '#react-navigation/native';
const HeaderRight = ({ navigation, target }) => {
const navigation = useNavigation();
return (
<Button transparent onPress={() => navigation.navigate(target)}>
<Icon name='plus' type='Entypo' style={{ fontSize: 26 }} />
</Button>
)
}
And you have to pass the target like below, as navigation is not accessible from there there is no point on passing that anyway.
headerRight: () => <HeaderRight target={'Profile'} />,
Hope this helps.
I solved it like this:
getting params in StackScreen - you need to pass to options route and navigation, and then you can get the route params like below:
<Stack.Screen
name='Patient'
component={PatientScreen}
options={({ route, navigation }) => {
return {
title: 'Карта пациента',
headerTintColor: '#2A86FF',
headerTitleAlign: 'center',
headerTitleStyle: {
fontWeight: 'bold',
fontSize: 20,
},
headerBackTitleVisible: false,
headerRight: () => (
<HeaderRight target={'AddAppointment'} patientId={route.params.patientId} />
),
}
}}
/>
then I get patientId in HeaderRight component and pass it to new screen, with second parameter with navigation like this (of course there is option to not use this component and pass it from Stack.Screen, but I did it to my own purpose):
const HeaderRight = ({ patientId, target }) => {
const navigation = useNavigation()
return (
<Button transparent onPress={() => navigation.navigate(target, { patientId })}>
<Icon name='plus' type='Entypo' style={{ fontSize: 26 }} />
</Button>
)
}
I get patientId in this third screen like below:
patientId: route.params?.patientId ?? '',
Related
I am trying to make an age text input for my app that if you are below 18 sets an error state and changes color. Here is my code:
function AgeButton() {
const [age, setAge] = useState('');
const [date, setDate] = useState(new Date(1598051730000));
const [modalVisible, setModalVisible] = useState(false);
const [error, setError] = useState(false);
const {header, modal, bottomModalView} = styles;
const today = new Date()
const minimumAgeYear = today.getFullYear() - 18
const onChange = (event: any, selectedDate: Date) => {
const currentDate = selectedDate || date;
// if (currentDate.getFullYear() > minimumAgeYear) {
// return setError(true);
// }
setDate(currentDate);
setAge(AgeCalculator(date));
};
return (
<View>
<Modal style={bottomModalView} isVisible={modalVisible} backdropOpacity={0} onBackdropPress={() => setModalVisible(false)}>
<View style={modal}>
<DateTimePicker
style={{alignItems: 'center', justifyContent: 'center', height: '70%'}}
testID="dateTimePicker"
value={date}
mode={'date'}
display="spinner"
// #ts-ignore
onChange={onChange}
// maximumDate={new Date(minimumAgeYear, today.getMonth(), today.getDay())}
textColor='#878787'
/>
<Text style={header}>How old are you?</Text>
</View>
</Modal>
<TextInput
onTouchStart={() => setModalVisible(true)}
editable={false}
autoComplete
mode="outlined"
label="Age"
value={age}
onChangeText={age => setAge(age)}
style={{maxHeight: 64, minWidth: '47%', marginRight: 16}}
activeOutlineColor={"#000"}
outlineColor={error ? '#ff3333' : (modalVisible ? "#000" : "#DBDBDB")}
theme={{
colors: {
text: "#000",
placeholder: error ? "#ff3333" : "#878787",
background: "#FFF"
}
}}
/>
</View>
);
}
I have got to the point where I could get the age to error if below 18 however I cannot get it to change if the input changes. Any help in how to do this would be great as originally I tried to just set an maximumDate on the DateTimePicker however this impacts UX as if a user picked their DOB the wrong way round the spinner would not let them
I just needed to set a turnary operator for the age:
function AgeButton() {
const [age, setAge] = useState('');
const [date, setDate] = useState(new Date(1598051730000));
const [modalVisible, setModalVisible] = useState(false);
const [error, setError] = useState(false);
const {header, modal, bottomModalView} = styles;
const today = new Date()
const onChange = (event: any, selectedDate: Date) => {
const currentDate = selectedDate || date;
age < '18' ? setError(true) : setError(false);
setDate(currentDate);
setAge(AgeCalculator(date));
};
return (
<View>
<Modal style={bottomModalView} isVisible={modalVisible} backdropOpacity={0} onBackdropPress={() => setModalVisible(false)}>
<View style={modal}>
<DateTimePicker
style={{alignItems: 'center', justifyContent: 'center', height: '70%'}}
testID="dateTimePicker"
value={date}
mode={'date'}
display="spinner"
// #ts-ignore
onChange={onChange}
// maximumDate={new Date(minimumAgeYear, today.getMonth(), today.getDay())}
textColor='#878787'
/>
<Text style={header}>How old are you?</Text>
</View>
</Modal>
<TextInput
onTouchStart={() => setModalVisible(true)}
editable={false}
autoComplete
mode="outlined"
label="Age"
value={age}
onChangeText={age => setAge(age)}
style={{maxHeight: 64, minWidth: '47%', marginRight: 16}}
activeOutlineColor={"#000"}
outlineColor={error ? '#ff3333' : (modalVisible ? "#000" : "#DBDBDB")}
theme={{
colors: {
text: error ? "#ff3333" : "#000",
placeholder: error ? "#ff3333" : "#878787",
background: "#FFF"
}
}}
/>
</View>
);
}
I am trying to make a stack navigator using reactstack navigation. When the button clicks, it appears on the detail screen only, the title of the page is detail. I am not yet to parsing data array to the next screen, it just tries to navigate the screen into the detail screen, and gets this error. I am new to react. Please help me solve this problem.
import React from 'react'
import {Button, StyleSheet, ScrollView, Text, View} from 'react-native'
import {useState, useEffect} from 'react'
import axios from 'axios'
const Item = ({id, user_id, title, onPress, navigation}) => {
return (
<View style={styles.container}>
<Text style={styles.text}>Id :{id}
</Text>
<Text style={styles.text}>User Id :{user_id}
</Text>
<Text style={styles.text}>Tittle :{title}
</Text>
<View style={styles.container}>
<Button onPress={() => navigation.navigate('Detail')} title='Detail'></Button>
</View>
<View style={styles.line}></View>
</View>
)
}
const Berita = () => {
const [users,
setUsers] = useState([]);
useEffect(() => {
getData();
}, []);
const selectItem = (item) => {
console.log('Selected item: ', item)
}
const getData = () => {
axios
.get('https://gorest.co.in/public/v1/posts')
.then(res => {
console.log('res: ', res);
setUsers(res.data.data);
})
}
return (
<ScrollView style={styles.container}>
{users.map(user => {
return <Item key={user.id} id={user.id} user_id={user.user_id} title={user.title}/>
})}
</ScrollView>
)
}
export default Berita
const styles = StyleSheet.create({
container: {
padding: 15
},
text: {
color: "black",
marginTop: 5,
fontStyle: 'italic',
fontSize: 18,
fontFamily: 'Arial'
},
line: {
height: 1,
backgroundColor: 'black',
marginVertical: 20
},
title: {
fontSize: 25,
fontWeight: 'bold',
textAlign: 'center',
color: "black"
},
tombol: {
padding: 10
}
})
This is the stack screen navigator code
const Tab = createBottomTabNavigator();
const Stack = createStackNavigator();
const DetailBerita = () => {
return (
<Stack.Navigator >
<Stack.Screen
name='Berita'
component={Berita}
options={{
headerTitleAlign: 'center'
}}/>
<Stack.Screen
name="Detail"
component={Detail}
options={{
headerTitleAlign: 'center'
}}/>
</Stack.Navigator>
)
}
It appears that you are using Stack Navigators with different screen names, but you didn't send it. If possible, can you send that file, I would be able to help you a bit better. But from what I have I can try and explain how Stack navigation works. With this line of code:
navigation.navigate('Detail')
You specify that you want to navigate to the screen named "Detail", if you want to navigate to another screen then you can change it to the name of the screen. Let's say you want to navigate to your home screen, and its named "Home" in your Stack.Navigation component. Simply change your navigation to the following:
navigation.navigate('Home')
This is happening because the navigation prop is passed to the Berita component and you are destructuring the property in Item component not in Berita.
So the code should look like
...
const Berita = ({ navigation }) => {
// ...
return (
<ScrollView style={styles.container}>
{users.map(user => {
return (
<Item
key={user.id}
id={user.id}
user_id={user.user_id}
title={user.title}
navigation={navigation} // Pass navigation
/>
);
})}
</ScrollView>
);
};
Another way is - you can just use navigation in onPress (Berita) and pass down onPress to Item component
const Item = ({ id, user_id, title, onPress }) => {
return (
<View style={styles.container}>
<Text style={styles.text}>Id :{id}</Text>
<Text style={styles.text}>User Id :{user_id}</Text>
<Text style={styles.text}>Tittle :{title}</Text>
<View style={styles.container}>
<Button onPress={onPress} title="Detail" />
</View>
<View style={styles.line}></View>
</View>
);
};
const Berita = ({ navigation }) => {
const [users, setUsers] = useState([]);
useEffect(() => {
getData();
}, []);
const selectItem = item => {
console.log('Selected item: ', item);
};
const getData = () => {
axios.get('https://gorest.co.in/public/v1/posts').then(res => {
console.log('res: ', res);
setUsers(res.data.data);
});
};
return (
<ScrollView style={styles.container}>
{users.map(user => {
return (
<Item
key={user.id}
id={user.id}
user_id={user.user_id}
title={user.title}
onPress={() => navigation.navigate('Detail')}
/>
);
})}
</ScrollView>
);
};
I am trying to get accustomed with React Native. Currently I have these nested FlatLists (where the first level displays a list of RenderedOrders, whereas these RenderedOrders themselves have a FlatList within them).
This is the main screen:
const ActiveScreen = () => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
const [isLoadingApi, setLoadingApi] = useState(true);
const [orderData, setOrderData] = useState([])
/* Fetch currently taken orders */
useEffect(() => {
getTakenOrders()
.then((data) => setData(data))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
/* Fetch order info from API */
useEffect(() => {
fetch('https://alessandro-visualizr.herokuapp.com/api/orders/NEFACTURAT')
.then((response) => response.json())
.then((json) => setOrderData(json))
.catch((error) => console.error(error))
.finally(() => setLoadingApi(false));
}, []);
return (
<View style={{ flex: 1, padding: 24 }}>
{isLoading || isLoadingApi ? <ActivityIndicator/> : (
<FlatList
data={data}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (RenderedOrder(item, orderData)) }
/>
)}
</View>
);
}
export default ActiveScreen;
While this is the above-mentioned component:
import React, {useEffect, useState} from "react";
import {FlatList, Text, View} from "react-native";
import {removeTakenOrder} from "../screens/OrderScreen";
function RenderedOrder(orderId, orderData) {
const [triggered, setTriggered] = useState(true);
return (
<View
style={{ flex: 1}}
>
<View
style={{ fontSize: 20, borderRadius: 5, borderWidth: 1,
marginBottom: 10, padding: 10, backgroundColor: 'rgba(34, 139, 34, 0.75)', color: 'black',
flex: 1 }}
>
<Text
style={{ fontSize: 24 }}
>
#{orderId}
</Text>
<View
style={{ alignItems: 'flex-end' }}
>
<Text
style={{ fontWeight: 'bold', color: 'red', fontSize: 20 }}
onPress={() => removeTakenOrder(orderId)
.then(() => alert("Order #" + orderId + " has been removed"))
}
>
X
</Text>
</View>
</View>
{true &&
<FlatList
data={orderData.filter((order) => (order.orderId === orderId))[0].products}
keyExtractor={({ id }, index) => id}
listKey = {orderId}
renderItem={({ item }) => (
<View>
<Text
style={{ fontSize: 18, padding: 5 }}
>
- {item.name}
<Text style={{ fontWeight: 'bold' }}> x{item.quantity} </Text>
</Text>
</View>
)}
/>
}
</View>
);
}
export default RenderedOrder;
However, when running this example I am confronted with this issue (due to RenderedOrder's state declaration):
Invalid hook call. Hooks can only be called inside the body of a function component.
I understand that in React, states can only be used within function and not class components. However I admit the differences between these two are not that clear to me. Am I commiting a mistake here?
You are using RenderedOrder as function instead of a functional component :
Change this:
renderItem={({ item }) => (RenderedOrder(item, orderData)) }
To this:
renderItem={({ item }) => <RenderedOrder item={item} orderData={orderData} /> }
Below is the code I want converted to hooks -
const App = () => {
const [visible, setVisible] = React.useState(false);
const openMenu = () => setVisible(true);
const closeMenu = () => setVisible(false);
const [barClicked, setbarClicked] = React.useState(false);
const [lineClicked, setlineClicked] = React.useState(false);
const [pieClicked, setpieClicked] = React.useState(false);
const BarCharts = () => {
const fill = 'rgb(134, 65, 244)'
const data = [50, 10, 40, 95, -4, -24, null, 85, undefined, 0, 35, 53, -53, 24, 50, -20, -80]
return (
<View style={styles.sectionContainer}>
<BarChart style={{ height: 200 }} data={data} svg={{ fill }} contentInset={{ top: 30, bottom: 30 }}>
<Grid />
</BarChart>
</View>
);
};
const LineCharts: () => React$Node = () => {
const data = [50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80]
return (
<View style={styles.sectionContainer}>
<LineChart
style={{ height: 200 }}
data={data}
svg={{ stroke: 'rgb(134, 65, 244)' }}
contentInset={{ top: 20, bottom: 20 }}
>
<Grid />
</LineChart>
</View>
);
};
const PieCharts: () => React$Node = () => {
const data = [50, 10, 40, 95, -4, -24, 85, 91, 35, 53, -53, 24, 50, -20, -80]
const randomColor = () => ('#' + ((Math.random() * 0xffffff) << 0).toString(16) + '000000').slice(0, 7)
const pieData = data
.filter((value) => value > 0)
.map((value, index) => ({
value,
svg: {
fill: randomColor(),
onPress: () => console.log('press', index),
},
key: `pie-${index}`,
}))
return (
<PieChart style={{ height: 200 }} data={pieData} />
);
};
return (
<Provider>
<View
style={{
paddingTop: 50,
flexDirection: 'row',
justifyContent: 'center',
}}>
<Menu
visible={visible}
onDismiss={closeMenu}
anchor={<Button onPress={openMenu}>Show menu</Button>}>
<Menu.Item onPress={() => setbarClicked(!barClicked)} title="Item 1" />
<Menu.Item onPress={() => setlineClicked(!lineClicked)} title="Item 2" />
<Menu.Item onPress={() => setpieClicked(!pieClicked)} title="Item 3" />
</Menu>
</View>
<View>
<Button onPress={() => setbarClicked(!barClicked)}></Button>
{barClicked && <BarCharts />}
<Button onPress={() => setlineClicked(!lineClicked)}></Button>
{lineClicked && <LineCharts />}
<Button onPress={() => setpieClicked(!pieClicked)}></Button>
{pieClicked && <PieCharts />}
</View>
<View style={styles.container}>
</View>
</Provider>
);
};
export default App;
Here's what it's suppose to do upong clicking SHOW MENU > Item 1. I tried doing it myself, but it's returning errors. - 'Can't find variable barClicked'. Below is what I came up with
export default class MyComponent extends React.Component {
state = {
visible: false,
barClicked: false,
lineClicked: false,
pieClicked: false
};
_openMenu = () => this.setState({ visible: true });
_closeMenu = () => this.setState({ visible: false });
_setbarClicked = () => this.setState({ barClicked: true });
_setlineClicked = () => this.setState({ barClicked: true });
_setpieClicked = () => this.setState({ barClicked: true });
render() {
return (
<Provider>
<View
style={{
paddingTop: 50,
flexDirection: 'row',
justifyContent: 'center'
}}>
<Menu
visible={this.state.visible}
onDismiss={this._closeMenu}
anchor={
<Button onPress={this._openMenu}>Show menu</Button>}>
<Menu.Item onPress={() => this._setbarClicked(!barClicked)} title="Item 1" />
<Menu.Item onPress={() => this._setlineClicked(!lineClicked)} title="Item 2" />
<Menu.Item onPress={() => this._setpieClicked(!pieClicked)} title="Item 3" />
</Menu>
</View>
<View>
<Button onPress={() => this._setbarClicked(!barClicked)}></Button>
{this.barClicked && <BarCharts />}
<Button onPress={() => this._setlineClicked(!lineClicked)}></Button>
{this.lineClicked && <LineCharts />}
<Button onPress={() => this._setpieClicked(!pieClicked)}></Button>
{this.pieClicked && <PieCharts />}
</View>
</Provider>
);
}
}
I have used BarChart, LineChart and PieChart from react-native-svg-chart library.
Issues
You don't reference any of your state variables correctly and your handlers don't consume any arguments. All your handlers also incorrectly reference your barClicked state.
_setbarClicked = () => this.setState({ barClicked: true });
_setlineClicked = () => this.setState({ barClicked: true });
_setpieClicked = () => this.setState({ barClicked: true });
Solution
If you want your handlers to take a parameter then adjust the implementation as follows:
_setbarClicked = (barClicked) => this.setState({ barClicked });
_setlineClicked = (lineClicked) => this.setState({ lineClicked });
_setpieClicked = (pieClicked) => this.setState({ pieClicked });
And adjust your callbacks to reference state correctly, i.e. this.state. barClicked.
render() {
const { barClicked, lineClicked, pieClicked } = this.state;
return (
...
<Menu.Item onPress={() => this._setbarClicked(!barClicked)} title="Item 1" />
<Menu.Item onPress={() => this._setlineClicked(!lineClicked)} title="Item 2" />
<Menu.Item onPress={() => this._setpieClicked(!pieClicked)} title="Item 3" />
...
<Button onPress={() => this._setbarClicked(!barClicked)}></Button>
{barClicked && <BarCharts />}
<Button onPress={() => this._setlineClicked(!lineClicked)}></Button>
{lineClicked && <LineCharts />}
<Button onPress={() => this._setpieClicked(!pieClicked)}></Button>
{pieClicked && <PieCharts />}
...
);
}
Suggestion
Since you are really just toggling these state values just do that in the handlers.
_setbarClicked = () => this.setState(prevState => ({ !prevState.barClicked }));
_setlineClicked = () => this.setState(prevState => ({ !prevState.lineClicked }));
_setpieClicked = () => this.setState(prevState => ({ !prevState.pieClicked }));
Then just attach as non-anonymous callback.
render() {
const { barClicked, lineClicked, pieClicked } = this.state;
return (
...
<Menu.Item onPress={this._setbarClicked} title="Item 1" />
<Menu.Item onPress={this._setlineClicked} title="Item 2" />
<Menu.Item onPress={this._setpieClicked} title="Item 3" />
...
<Button onPress={this._setbarClicked}></Button>
{barClicked && <BarCharts />}
<Button onPress={this._setlineClicked}></Button>
{lineClicked && <LineCharts />}
<Button onPress={this._setpieClicked}></Button>
{pieClicked && <PieCharts />}
...
);
}
You need to place the state object in constructor (preferably) in class components.
export default class MyComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
visible: false,
barClicked: false,
lineClicked: false,
pieClicked: false
};
}
...
and change your calls from this._setbarClicked(!barClicked) to this._setbarClicked(!this.state.barClicked)
Is there a way to show on the screen a picked date?
I tried to make a date picker and show the picked date on the screen close to each button.
For example, if I select any date, I want to display the date near the button.
How can I do this the right way?
I added a Snack expo for my example:
SNACK
import React, { useState } from "react";
import { View, Button, Platform, StyleSheet, TextInput } from "react-native";
import DateTimePicker from "#react-native-community/datetimepicker";
const MyDatePicker = () => {
const [date, setDate] = useState(new Date(1598051730000));
const [mode, setMode] = useState("date");
const [show, setShow] = useState(false);
const onChange = (event, selectedDate) => {
const currentDate = selectedDate || date;
setShow(Platform.OS === "ios");
setDate(currentDate);
};
const showMode = currentMode => {
setShow(true);
setMode(currentMode);
};
const showDatepicker = () => {
showMode("date");
};
const showTimepicker = () => {
showMode("time");
};
return (
<View style={styles.container}>
<View>
<Button
style={{ marginRight: 10 }}
onPress={showDatepicker}
title="FROM DATE"
/>
</View>
<View>
<Button
style={{ marginRight: 10 }}
onPress={showDatepicker}
title="TO DATE"
/>
{/* <Button onPress={showTimepicker} title="Show time picker!" /> */}
</View>
{show && (
<DateTimePicker
testID="dateTimePicker"
timeZoneOffsetInMinutes={0}
value={date}
mode={mode}
is24Hour={true}
display="default"
onChange={onChange}
/>
)}
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
marginTop: 50,
paddingBottom: 550,
justifyContent: "space-between",
flexDirection: "row",
marginHorizontal: 80
}
});
export default MyDatePicker;
You can do something like this, I had made some changes in your code
import React, { useState } from "react";
import { View, Button, Platform, StyleSheet, TextInput, Text } from "react-native";
import DateTimePicker from "#react-native-community/datetimepicker";
const MyDatePicker = () => {
const today = new Date();
const [date1, setDate1] = useState(new Date(today));
const [date2, setDate2] = useState(new Date(today));
const [mode, setMode] = useState("date");
const [show1, setShow1] = useState(false);
const [show2, setShow2] = useState(false);
const onChange1 = (event, selectedDate) => {
const currentDate = selectedDate || date;
setShow1(Platform.OS === "ios");
setDate1(currentDate);
};
const onChange2 = (event, selectedDate) => {
const currentDate = selectedDate || date;
setShow2(Platform.OS === "ios");
setDate2(currentDate);
};
const showMode1 = currentMode => {
setShow1(true);
setMode(currentMode);
};
const showMode2 = currentMode => {
setShow2(true);
setMode(currentMode);
};
const showDatepicker1 = () => {
showMode1("date");
};
const showDatepicker2 = () => {
showMode2("date");
};
const showTimepicker = () => {
showMode("time");
};
return (
<View style={styles.container}>
<View style={{marginLeft: 20}}>
<Button
onPress={showDatepicker1}
title="FROM DATE"
/>
</View>
<View>
<Text>{date1.toISOString().slice(0,10)}</Text>
</View>
<View style={{marginLeft: 20}}>
<Button
onPress={showDatepicker2}
title="TO DATE"
/>
{/* <Button onPress={showTimepicker} title="Show time picker!" /> */}
</View>
<View>
<Text>{date2.toISOString().slice(0,10)}</Text>
</View>
{show1 && (
<DateTimePicker
testID="dateTimePicker"
timeZoneOffsetInMinutes={0}
value={date1}
mode={mode}
is24Hour={true}
display="default"
onChange={onChange1}
/>
)}
{show2 && (
<DateTimePicker
testID="dateTimePicker"
timeZoneOffsetInMinutes={0}
value={date2}
mode={mode}
is24Hour={true}
display="default"
onChange={onChange2}
/>
)}
</View>
);
};
const styles = StyleSheet.create({
container: {
alignItems:"center",
flex: 1,
marginTop: 50,
paddingBottom: 550,
flexDirection: "row",
}
});
export default MyDatePicker;
I had added two text components where you can show the date.
Hope this helps!