React Native: Back Button Closes Modal - react-native

I'm trying to make a text open a modal when the user pressed on it and closes when they press on the back button. The modal does not open when the user clicks on the text. I tried following the solution from other questions but it doesn't work and their modal are not in a separate component.
Login.js
const [modalOpen, setModalOpen] = useState(false);
return (
<CustomScrollView>
<ForgotPassword open={modalOpen}/> //Modal
<ForgotPasswordText onPress={() => setModalOpen(true)}>Forgot Password?</ForgotPasswordText>
</CustomScrollView>
);
ForgotPassword.js
const ForgotPassword = ({open}) => {
const [invisible, setInvisible] = useState({open});
return (
<Modal
statusBarTranslucent
transparent= {true}
visible={invisible}
animationType="fade"
onRequestClose={() => {setInvisible(!open);}}>
<CenteredModal>
<ModalView>
<ForgotPasswordTitle>Forgot Password</ForgotPasswordTitle>
</ModalView>
</CenteredModal>
</Modal>
);
}

Both components are mounted already. If you are changing the modalOpen state in your root component, it would not trigger the modal to be opened in the ForgotPassword component in the way it is implemented.
One solution would be to pass the modalOpen prop right away and using it in your Modal component for the visible prop. But you would need to pass your setModalOpen function from your Login component to remain the state, too.
const [modalOpen, setModalOpen] = useState(false);
return (
<CustomScrollView>
<ForgotPassword open={modalOpen} setOpen={setModalOpen} /> //Modal
<ForgotPasswordText onPress={() => setModalOpen(true)}>Forgot Password?</ForgotPasswordText>
</CustomScrollView>
);
const ForgotPassword = ({open, setOpen}) => (
<Modal
statusBarTranslucent
transparent={true}
visible={open}
animationType="fade"
onRequestClose={() => setOpen(!open)}>
<CenteredModal>
<ModalView>
<ForgotPasswordTitle>Forgot Password</ForgotPasswordTitle>
</ModalView>
</CenteredModal>
</Modal>
);
Find it working here:
https://codesandbox.io/s/broken-night-lu8e96

Related

React Navigation, Please attach a method to this component

I am trying to navigate to a route using onPress, but get the error: Please attach a method to this component I need the whole component clickable, button and text - is that possible?
<TouchableOpacity
style={styles.widgetCont}
onPress={() => navigate(AppRoutes.Settings.Name)}
>
<Text style={styles.widgetText}>{setupRemindersDescription}</Text>
<Button
title={setupRemindersLabel}
buttonStyle={[buttons.primarySpace, styles.widgetBTN]}
titleStyle={buttons.smallTitle}
/>
</TouchableOpacity>
This doesnt give me the error and navigates fine:
<TouchableOpacity
style={VehicleStyles.widgetCont}
onPress={async () => {
const success = await tryBiometrics();
if (success) {
Linking.openURL(BookRepairUrl);
}
}}
>
<Button
title={myVehicles.booknow}
buttonStyle={[buttons.primarySpace, VehicleStyles.widgetBTN]}
titleStyle={buttons.smallTitle}
/>
</TouchableOpacity>
I need the whole component clickable, button and text - is that possible?
for that you can use Pressable from react-native.

react native textinput lost focus after 1 char type

I have this problem with ios but not with android. It only disturb the add task input the task edit and the list name edit. The input addList(It's the one with "What to do?" on the draw) in the header works fine.
UI drawing
Achitecture of components
I console log my component and I can see it rerender everytime I add a letter in the input field.
I checked on google and follow this:(can we link other website here?) https://www.codegrepper.com/code-examples/javascript/react+native+textinput+lost+focus+after+charter+type
Tried the the first solution with onBlurr and onFocus.
I tried to make a TextInput component for add task.
I even try with my component addList but it didn't solve the problem.
Anyone have faced this problem before? Is there anyway to by pass this?
My code without the import/style look like this:
const TaskList: FunctionComponent<TasksListProps> = ({
addTask,
deleteTask,
toggleTask,
editTaskName,
...props
}) => {
console.log('props', props);
const [nameOfTask, setNameOfTask] = useState('');
console.log('name', nameOfTask);
const textHandler = (enteredName: string) => {
setNameOfTask(enteredName);
};
const handleSubmitTask = () => {
if (nameOfTask === '') {
return;
}
addTask(props.listId, nameOfTask);
setNameOfTask('');
};
return (
<View style={styles.tasksListContainer}>
{props.tasks.map(task => (
<SingleTask
key={task.id}
task={task}
listId={props.listId}
deleteTask={deleteTask}
toggleTask={toggleTask}
editTaskName={editTaskName}
/>
))}
<View style={styles.taskInputContainer}>
<TextInput
style={styles.tasksTextInput}
value={nameOfTask}
onChangeText={textHandler}
placeholder="Write a task to do"
/>
<TouchableOpacity onPress={handleSubmitTask}>
<Image source={require('./Img/add-button.png')} />
</TouchableOpacity>
</View>
</View>
);
};
You can create a HOC and wrap your screen width DismissKeyboard
import { Keyboard } from 'react-native';
const DismissKeyboard = ({ children }) => (
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
{children}
</TouchableWithoutFeedback>
);
That because Re render.
Try to make the input with the main component of the page to test it.
Then check where the error with re-render

How to change state of react hook inside other component

Senario
I have a dialog, it look something like this, it have hook for showing this dialog, called showDialog , and dialog have a button with Onpress method
export default function DialogTesting(show: boolean) {
const [showDialog, doShow] = useState(show)
return (
<View>
{/* <Button
title="click"
onPress={() => {
setShow(true)
}}
>
<Text>Show dialog</Text>
</Button> */}
<Dialog
visible={showDialog}
title="Record New Progress"
style={DIALOG}
onClose={() => {
doShow(false)
}}
>
And a main sceen , it also have hook to show dialog, called show,
export const MedicalRecord = memo(function MedicalRecord() {
// const onPressViewAll = useCallback(() => {}, [])
const [show, setShow] = useState(false)
function hanndleDialog() {
setShow(!show)
}
return (
<SummaryViewContainer
count={5}
title={"dashboardScreen.medicalRecords.title"}
onPress={() => {
hanndleDialog()
}}
>
<View>
{show && (
<ProgressDialog
show={show}
callback={() => {
hanndleDialog()
}}
/>
)}
<RecordItem />
<RecordItem />
<RecordItem />
</View>
</SummaryViewContainer>
)
})
Problem
When i click the button in main screen, change hook show to true to show dialog, and use this hook state in dialog to set show in dialog to true to show that dialog, and in dialog, when i click button to close dialog, it disappear, but problem is, the state of show in main screen remain true, so i have to press twice to show dialog again
Question
How can i change hook status in main screen, or how can i press close button in dialog, the show hook in main screen return false, i tried to change state of mainscreen in dialog but it won't work
Here is a short video of problem
https://streamable.com/9mm26t
You should maintain just one copy of your state in the parent component itself. Then pass "show" and "setShow" as props to the child component.
Parent Component:
export const MedicalRecord = memo(function MedicalRecord() {
// const onPressViewAll = useCallback(() => {}, [])
const [show, setShow] = useState(false)
function hanndleDialog() {
setShow(!show)
}
return (
<SummaryViewContainer
count={5}
title={"dashboardScreen.medicalRecords.title"}
onPress={() => {
hanndleDialog()
}}
>
<View>
{show && (
<ProgressDialog
show={show}
setShow = {setShow}
/>
)}
<RecordItem />
<RecordItem />
<RecordItem />
</View>
</SummaryViewContainer>
)
})
Dialog Component:
export default function DialogTesting({show, setShow}) {
return (
<View>
{/* <Button
title="click"
onPress={() => {
setShow(true)
}}>
<Text>Show dialog</Text>
</Button> */}
<Dialog
visible={show}
title="Record New Progress"
style={DIALOG}
onClose={() => {
setShow(false)
}}
>
</View>
)
}
It looks like you have 2 versions of local state at each component. You need to keep 1 version of "show" at the top most parent where you care to control this variable and then pass it down as a prop to your child components. Then on your child components you need to expose a callback that the parent will pass down and the child will call to trigger what occurs when the button is clicked in the child component.

How to reset state when navigating away from page

I have a map that triggers a modal when I click on a marker. The modal is a touchable which navigates to another page. When the page is dismissed and the user returns to the Home page (in this case), it is not possible to touch another marker and trigger a new modal. Any idea how I should set this up so that it is reset when navigating back to home? Some code below:
constants in my functional component that set state:
const [modalVisible, setModalVisible] = useState(false);
const [selectedMarker, setSelectedMarker] = useState(false);
const markerPressed = (marker) => {
setModalVisible(true);
setSelectedMarker(marker);
};
const markerLink = (selectedMarker) => {
setModalVisible(false);
onPressListingItem(selectedMarker);
};
The marker with the param to trigger modal:
<CustomMarker
onPress={() => {
markerPressed(listing);
}}
/>
The modal with param to navigate to page:
<Modal
style={{ position: 'absolute', bottom: 10 }}
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}
setModalVisiblity={() => {
setModalVisible((preState) => (preState = !preState));
}}>
Solution 1: You could reset the data in the same place you trigger your Modal, in your markerPressed function. That way when you return, the data would be reset.
Solution 2: If you are using react-navigation, you could add a focus listener to check when your mp page comes back into focus.
navigation.addListener('focus', () => {
// reset marker state
});

How to show component when a function is called in ReactNative (Like Alert.alert())

I would to create a custom component to be rendered when a function is called in ReactNative. Is like a alert() component. In this case i don't want use a modal, a want to make a component that can showed in screen when a function is called. Someone have any ideia about how i can made this?
I want to make this:
const Example = () => {
return(
<View>
<Button title="Show Modal" onPress={showModal}/>
</View>
)
}
I can't make this:
const Example = () => {
const [isVisible, setIsVisible] = useState(false);
return(
<View>
<Modal visible={isVisible}>
<Text>Awesome code here ...</Text>
</Modal>
<Button title="Show Modal" onPress={() => {setIsVisible(true)}}/>
</View>
)
}
What i want to do is show the component whitout put her jsx in my return. I need to call a function, when this function is called my componnent is showed in screen. The logic is same of Alert.alert() function.