So I've been looking for a dropdown picker to be toggled on "on Press" since yesterday yet I found nothing, all I want is to put an icon in a "touchable Opacity", and when pressed the dropdown picker shows.
I've been advised to use "react-native-picker-select" library, I imported it and added the usage advised by the library like this
const Dropdown = () => {
return (
<RNPickerSelect
onValueChange={(value) => console.log(value)}
items={[
{ label: 'Football', value: 'football' },
{ label: 'Baseball', value: 'baseball' },
{ label: 'Hockey', value: 'hockey' },
]}
/>
); };
then I called it from the "on Press" but its showing nothing, so what am I missing?
I think you are trying to call whole element on pressing the button, but there is no need to do that because react-native-picker-select by default supports on press focus which you want. While native 'Picker' from 'react-native' does not support that.
So, you can add this directly like a View or TouchableOpacity.
For example:
const App = () => {
return (
<View />
<RNPickerSelect />
...
);
}
Related
React Native Dropdown Picker is the most popular library to implement a dropdown in React Native. But in the library, I could not find a way to customize the dropdown arrow and the ticks in the dropdown list. They are by default in black color and cannot be customized with my knowledge.
Basic implementation:
import DropDownPicker from 'react-native-dropdown-picker';
function App() {
const [open, setOpen] = useState(false);
const [value, setValue] = useState(null);
const [items, setItems] = useState([
{ label: 'ice-cream', value: '1' },
{ label: 'strawberry', value: '2' },
{ label: 'grapes', value: '3' },
{ label: 'fruit salad', value: '4' },
{ label: 'jello', value: '5' },
{ label: 'apple', value: '6' },
]);
return (
<DropDownPicker
open={open}
value={value}
items={items}
setOpen={setOpen}
setValue={setValue}
setItems={setItems}
/>
);
}
Sample Output:[Click here to see the output]2
There is a prop in the called arrowIconStyle. But for that also, I could not find a way to give a color as a style.
Ex: arrowIconStyle={{color: 'white'}}
Unfortunately this does not work and gives an error:
Type '{ color: string; }' is not assignable to type
'StyleProp'.ts(2322)
Can someone please help me regarding this?
Thank you.
try to change the arrow icon and implement your own styles for the icon
like the following:
https://snack.expo.dev/#hewr/57a779
//to change the dropdown box style
dropDownContainerStyle={{
backgroundColor: "#dfdfdf"
}}
// to style the selected item style
selectedItemContainerStyle={{
backgroundColor: "grey"
}}
for more details visit their website
and check the Dropdown and List and Items sections
How do I make the return button on the mobile keyboard send the message instead of creating a new line? I tried using onSubmitEditing in the textInputProps but couldn't get it to work.
You need to implement your own ChatComposer and pass the onSubmitEditing prop in the textInputProps in there. In order to prevent keyboard dismiss you also need to set blurOnSubmit to false.
const [messages, setMessages] = useState([])
const onSend = useCallback((messages = []) => {
setMessages((previousMessages) => GiftedChat.append(previousMessages, messages))
}, [])
const ChatComposer = (
props: ComposerProps & {
onSend: SendProps<IMessage>["onSend"]
text: SendProps<IMessage>["text"]
}
) => {
return (
<Composer
{...props}
textInputProps={{
...props.textInputProps,
blurOnSubmit: false,
multiline: false,
onSubmitEditing: () => {
if (props.text && props.onSend) {
props.onSend({ text: props.text.trim() }, true)
}
},
}}
/>
)
}
return (
<GiftedChat messages={messages} onSend={onSend} renderComposer={ChatComposer} />
)
If you want to remove the default send button from the text input field on the right, you need to pass a custom renderSend button, which could be empty, e.g.
renderSend={() => {}}
Notice, that I have tested all of the above on iOS only. Android might behave differently.
How to detect user leaving a screen in React Native and act accordingly ?
For an example when user tries to leave current screen alert should popup and say You have unsaved changes, are you sure you want to leave?. If yes user can leave the screen, if no user should be in same screen.
import { useFocusEffect } from '#react-navigation/native';
import {Alert} from 'react-native'
const Profile = (props) => {
useFocusEffect(
React.useCallback(() => {
// Do something when the screen is focused
return () => {
// Do something when the screen is unfocused
// Useful for cleanup functions
Alert.alert(
'Want to leave',
'You have unsaved changes, are you sure you want to leave?',
[
{
text: 'yes',
onPress: () => {
// should leave to the screen user has navigate
},
},
{ text: 'no', onPress: () => null },
],
true
)
};
}, [])
);
return <ProfileContent />;
}
export default Profile
Currently I'm facing few problems with this code.
Alert will popup once user already navigate to selected navigation screen. But I want Alert to be popup before user navigate to the selected screen.
If user selected no, User should be remain in the same screen.
Is there a way to achieve these things ?
Thanks.
Answer
function EditText({ navigation }) {
const [text, setText] = React.useState('');
const hasUnsavedChanges = Boolean(text);
React.useEffect(
() =>
navigation.addListener('beforeRemove', (e) => {
if (!hasUnsavedChanges) {
// If we don't have unsaved changes, then we don't need to do anything
return;
}
// Prevent default behavior of leaving the screen
e.preventDefault();
// Prompt the user before leaving the screen
Alert.alert(
'Discard changes?',
'You have unsaved changes. Are you sure to discard them and leave the screen?',
[
{ text: "Don't leave", style: 'cancel', onPress: () => {} },
{
text: 'Discard',
style: 'destructive',
// If the user confirmed, then we dispatch the action we blocked earlier
// This will continue the action that had triggered the removal of the screen
onPress: () => navigation.dispatch(e.data.action),
},
]
);
}),
[navigation, hasUnsavedChanges]
);
return (
<TextInput
value={text}
placeholder="Type something…"
onChangeText={setText}
/>
);
}
for more information refer: https://reactnavigation.org/docs/preventing-going-back/
This will prevent user to going back from one screen to another. But this does not prevent tab navigation because screen does not get removed.
prevent from tab navigation
<Tab.Screen
name={'search'}
component={SearchNavigator}
options={{
tabBarIcon: ({ focused, color }) => (
<View>
<Icon
name='search1'
color={
focused
? 'black'
: 'white'
}
size={25}
/>
</View>
),
}}
listeners={{
tabPress: (e) => {
if (true) {
// Prevent default action
e.preventDefault()
// Prompt the user before leaving the screen
Alert.alert(
'Discard changes?',
'You have unsaved changes. Are you sure to discard them and leave the screen?',
[
{
text: "Don't leave",
style: 'cancel',
onPress: () => {},
},
{
text: 'Discard',
style: 'destructive',
// If the user confirmed, then we dispatch the action we blocked earlier
// This will continue the action that had triggered the removal of the screen
onPress: () =>
navigationRef.current?.navigate(
'search',
{}
),
},
]
)
}
},
}}
/>
You can add listener tabPress like above code and provide an Alert.
I am using react material-table. I am in need of a feature like this: I use remote data mode to get a list of records, then I use the custom column rendering function to add a Material Button at the end of each row in the table, When the user presses this button I want it to be hidden. How can I do that. I look forward to receiving your help.
This is the illustration image
I made this example, on button click it gets disabled and a variable is set to to a loading state:
The key aspect here is to define something that identifies the row that is being updated. I use an extra column on which you could also display a spinner component:
{
field: "isUpdating",
render: (rowdata) =>
fetchingClient === rowdata.name
? "loading.." // Add your <Spinner />
: null
},
Since you want to render the button as a custom column (other way could be using actions), on the render attribute of that column, you can use rowdata parameter to access what you are looking for:
{
field: "join",
sorting: false,
render: (rowdata) => (
<button
disabled={fetchingClient === rowdata.name}
onClick={(event) => fetchDataFromRemote(rowdata.name)}
>
Go fetch
</button>
)
}
Here is the link to the sandbox and the complete code, I hope this works for you!
import React, { Fragment, useState } from "react";
import MaterialTable from "material-table";
export default function CustomEditComponent(props) {
const [fetchingClient, setFetchingClient] = useState("");
const fetchDataFromRemote = (clientName) => {
console.log(clientName);
setFetchingClient(clientName);
};
const tableColumns = [
{ title: "Client", field: "client" },
{ title: "Name", field: "name" },
{
field: "isUpdating",
render: (rowdata) =>
fetchingClient === rowdata.name
? "loading.." // Add your <Spinner />
: null,
},
{
field: "join",
sorting: false,
render: (rowdata) => (
<button
disabled={fetchingClient === rowdata.name}
onClick={(event) => fetchDataFromRemote(rowdata.name)}
>
Go fetch
</button>
),
},
];
const tableData = [
{
client: "client1",
name: "Jasnah",
year: "2019",
},
{
client: "client2",
name: "Dalinar",
year: "2018",
},
{
client: "client3",
name: "Kal",
year: "2019",
},
];
return (
<Fragment>
<MaterialTable
columns={tableColumns}
data={tableData}
title="Material Table - custom column "
options={{ search: false }}
/>
</Fragment>
);
}
Clicking on the navbar button the drawer is not opening.
Here is code i have used for button press
if (event.type === 'NavBarButtonPress') {
if (event.id === 'sideDrawerToggle') {
this.props.navigator.toggleDrawer({
side: 'left',
animated: true,
});
}
}
Here is the drawer set up
Navigation.startTabBasedApp({
tabs: [
{
label: 'Find Place',
screen: 'places.FindPlace',
title: 'Find Place',
icon: source[0],
navigatorButtons: {
leftButtons: [
{
icon : source[2],
title : 'Menu',
id: 'sideDrawerToggle'
}
]
}
},
{
label: 'Share Place',
screen: 'places.SharePlace',
title: 'Share Place',
icon: source[1],
navigatorButtons: {
leftButtons: [
{
icon: source[2],
title: 'Menu',
id: 'sideDrawerToggle'
}
]
}
}
],
drawer: {
left: {
screen: 'places.SideDrawer'
}
}
});
And this is what my drawer looks like
import React, {Component} from 'react';
import {View, Text, Dimensions} from 'react-native';
class SideDrawer extends Component {
render() {
return(
<View style={[
styles.container,
{width: Dimensions.get('window').width * 0.8}
]}>
<Text>Drawer</Text>
</View>
);
}
}
const styles = {
container: {
backgroundColor : 'white',
paddingTop: 22,
flex: 1
}
};
export default SideDrawer;
By searching a lot i found that giving a fixed width to drawer solves the problem. But its not solving in my case. I don't know what is wrong with the code, It was working fine.
You can simply use
this.props.navigation.openDrawer();
in your screen .
please check official doc and example from the following link
https://reactnavigation.org/docs/en/drawer-based-navigation.html
https://reactnavigation.org/blog/#drawer-routes-have-been-replaced-with-actions
You can specify a built-in button in your navigatorButtons with id: 'sideMenu' and it will do the magic for you. ie.
...
navigatorButtons: {
leftButtons: [
{
id: "sideMenu"
}
]
},
...
I don't think that is the right way of setting up the drawer navigation. Check out the oficial documentation here: https://reactnavigation.org/docs/navigators/drawer. It shows that each component that the drawer will navigate to is a scene that you define and set up in the Main Component of the app.
I also recommend using the Drawer from NativeBase.io https://docs.nativebase.io/Components.html#Drawer. Which gives you a better look and feel on both iOS and Android, it looks more native to both.
Are you using an iPhone? It seems there's a bug to this in the wix one which affects them but not Android.
Deep links might work https://wix.github.io/react-native-navigation/#/deep-links