I am trying to dismiss the snack bar after the user presses ok or after the duration. I tried passing an extra variable to the component and changing state but it does not work. Here is my code for the LogIn page that uses the snackbar component that renders only after a bad login request , its not the whole code:
const [error, setError] = React.useState(false);
const [username, setUsername] = React.useState('');
const [password, setPassword] = React.useState('');
const [visible, setVisible] = React.useState(false);
/* const form = createForm(data); */
return (
<View style={Style.container}>
{error && (
<View style={{width: '30%', height: '10%'}}>
<Snack_alert
message={'Wrong username or password!'}
textcolor={'white'}
btn_color={'white'}
snack_color={'red'}
dismiss={() => {
setVisible(false);
}}
/>
</View>
)}
and here is the child component:
export default function Snack_alert({
message,
textcolor,
btn_color,
snack_color,
dismiss
}) {
return (
<Snackbar
visible={true}
onDismiss={() => {
{
dismiss
}
}}
duration={2500}
theme={{
colors: {
surface: textcolor,
accent: btn_color,
onSurface: snack_color,
},
}}
//surface: text color , accent: undo color, onSurface: snackbar color
action={{
label: 'Ok',
onPress: () => {
{
dismiss
}
},
}}>
{message}
</Snackbar>
);
}
Also later in my code I update the setError to true so that I can render the snackbar , I am unsure if that causes any problems. Thanks in advance!
CodePudding user response:
The way you pass the prop dismiss
to the Snack_alert
component from the parent container is correct. The prop dismiss
holds a function. Thus,
onDismiss={() => {
{
dismiss
}
}}
is basically the same as writing
function dismiss() {
setVisible(false)
}
function onDismiss() {
{
dismiss
}
}
Let us log what will happen if we call onDismiss()
. This yields
undefined
since onDismiss
does not return anything. Let us return dismiss
and see what will happen.
function onDismiss() {
{
return dismiss
}
}
If we call onDismiss
again it yields the following output.
function dismiss() {
setVisible(false);
}
The function dismiss
is now correctly returned, but it is not called. This is fine if you know that the Snackbar
component will internally do something like this.
const foo = onDismiss()
foo()
The constant foo
gets assigned the return value of the function onDismiss
which is the function dismiss
that we have passed as a prop. We can call dismiss
by calling foo
. This will correctly set the visible state to false
. Notice that it is more convenient to write
onDismiss={dismiss}
since then the prop onDismiss
gets the prop dismiss
assigned which is the function dismiss
that we have passed earlier. Thus, instead of calling onDismiss
as a function in order to retrieve dismiss
, the Snackbar
container can now directly call onDismiss()
and this will call dismiss()
.
My last comment is how the Snackbar
component works. It expects the following.
<Snackbar
visible={visible}
onDismiss={() => setVisible(false)}
...
/>
Thus, onDismiss
is a function that when called sets the visible
state of the component. Hence, you need to fix two things.
- Change the way you are passing the function
dismiss
. - Pass the visible state to
Snack_alert
from the parent container.
By knowing this, we can construct a working version of your code as follows.
onst [error, setError] = React.useState(false);
const [username, setUsername] = React.useState('');
const [password, setPassword] = React.useState('');
const [visible, setVisible] = React.useState(false);
/* const form = createForm(data); */
return (
<View style={Style.container}>
{error && (
<View style={{width: '30%', height: '10%'}}>
<Snack_alert
message={'Wrong username or password!'}
textcolor={'white'}
btn_color={'white'}
snack_color={'red'}
visible={visible}
dismiss={() => {
setVisible(false);
}}
/>
</View>
)}
...
export default function Snack_alert({
message,
textcolor,
btn_color,
snack_color,
dismiss,
visible
}) {
return (
<Snackbar
visible={visible}
onDismiss={dismiss}
duration={2500}
theme={{
colors: {
surface: textcolor,
accent: btn_color,
onSurface: snack_color,
},
}}
//surface: text color , accent: undo color, onSurface: snackbar color
action={{
label: 'Ok',
onPress: dismiss,
}}>
{message}
</Snackbar>
);
}
CodePudding user response:
action={{ label: 'Ok', onPress: () => { { dismiss } }, }}
You don't call the dismiss-function. Either add parenthesis:
onPress: () => {
dismiss()
}
Or just pass the function directly:
onPress: dismiss