How to change state of react hook inside other component - react-native

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.

Related

Creating Modal Object need help dealing with isVisible state

I am currently trying to create a Modal object using react-native-modal like this
const ModalExample = (props) => {
return (
<Modal isVisible={props.isVisible}>
<Text>Hello!</Text>
<Button title="Hide modal" onPress={this.setModalVisibility} />
</Modal>
)
}
The problem is that the onPress is supposed to change the state from true to false but doesn't have access to the state within the class.
Here is the button that initializes the modal and how i'm calling the object:
<Button title="Show modal" onPress={this.setModalVisibility} />
<ModalExample isVisible={this.state.modalVisible}/>
and just incase here is my setModalVisibility that is within the class
setModalVisibility = () =>{
this.setState({modalVisible: !this.state.modalVisible})
}
Thanks for any help
You need to pass the function as well,
<ModalExample isVisible={this.state.modalVisible} setModalVisibility={this.setModalVisibility}/>
Call that function in modal,
const ModalExample = (props) => {
return (
<Modal isVisible={props.isVisible}>
<Text>Hello!</Text>
<Button title="Hide modal" onPress={props.setModalVisibility} />
</Modal>
)
}
Note: You don't have access to this in functional component.

Passing values dynamically to child component react native

App.js
render() {
return (
<View style={{ flex: 1, marginTop: 20 }}>
<Button
title="Learn More"
color="#841584"
accessibilityLabel="Learn more about this purple button"
onPress={() => {
(this.state.dadda = '2017-09-07');
}}
/>
<EventCalendar
eventTapped={this._eventTapped.bind(this)}
events={this.state.events}
width={width}
initDate={this.state.dadda}
scrollToFirst={false}
/>
</View>
); }
This is my parent component ,I want to pass initDate to event calendar component,I want to update the date when the button is pressed?
You should not mutate the state by assigning value to the state variable directly but instead use setState to acheive that.
<Button
title="Learn More"
color="#841584"
accessibilityLabel="Learn more about this purple button"
onPress={() => this.setState({dadda: '2017-09-07'})}
/>
The way you are setting dadaa into the state is not correct, use this.setState function instead, have a look at the doc.
Change your onPress handler to
...
< Button
title = "Learn More"
color = "#841584"
accessibilityLabel = "Learn more about this purple button"
onPress = {
() => {
this.setState({
dadda:'2017-09-07'
});
}
}
/>
...
Also, don't declare the function inside render, rather keep it at the class level like
onPressHandler = () => {
this.setState({
dadaa: 'aaaa'
});
}
render() {
return (
...
<
Button
...
onPress = {this.onPressHandler}
...
/>
...
);
}
Hope this will help!

React Native + Redux Form : Wizard Form handleSubmit

I am trying to create wizard form in react native with the help of this example. but handleSubmit is not working.
Signup.js
submitForm(values){
console.log("formValues",values);
}
nextPage(){
this.setState({ page: this.state.page + 1 });
}
render(){
const { page } = this.state;
{page === 1 && <WizardFormFirstPage nextPage={this.nextPage} />}
{page === 2 && <WizardFormSecondPage nextPage={this.nextPage} />}
{page === 3 && <WizardFormThirdPage onSubmit={this.submitForm} />}
}
WizardFormFirstPage and WizardFormSecondPage works fine. but when it comes on WizardFormThirdPage it doesn't do anything (I can't see any console log in my terminal for validations and submitForm function). here is the code written.
WizardFormThirdPage.js
const WizardFormThirdPage = props => {
const { handleSubmit, onSubmit } = props;
return (
<View>
<Field name="street" component={InputField} label="Street" />
<Button style= {{ margin: 10 }} block primary onPress={handleSubmit(onSubmit)}>
<Text>Continue</Text>
</Button>
</View>
);
};
export default reduxForm({
form: 'signup', // <------ same form name
destroyOnUnmount: false, // <------ preserve form data
forceUnregisterOnUnmount: true, // <------ unregister fields on unmount
validate,
})(WizardFormThirdPage);
This is probably too late but I figured out what I was doing wrong.
While wrapping the react native InputText component with the redux form Field component. We have to pass props to the InputText component. I was passing props like this ...
<InputText {...props} />
The {...props} attaches all the event handlers like onChange, onSubmit, etc to the component so we don't have to do it manually. The issue lies here, that the InputText component has a onChangeText property rather than onChange which redux form injects into the props.
The correct way to do this is ..
const renderInput = ({ input: { onChange, ...restInput }}) => {
return <TextInput style={styles.input} onChangeText={onChange} {...restInput} />
}
const Form = props => {
const { handleSubmit } = props
return (
<View style={styles.container}>
<Text>Email:</Text>
<Field name="email" component={renderInput} />
<TouchableOpacity onPress={handleSubmit(submit)}>
<Text style={styles.button}>Submit</Text>
</TouchableOpacity>
</View>
)
}
This answer came from the article Simple React Native forms with redux-form.

Where to trigger Modal-components in React Native?

I have a list of items in my app. When the user clicks on a list item I want to show more details in a . I could put the details-component into the list item component and hide it by default.
Is there a better way?
Assuming you will only be displaying a single Modal at a time. You can create the Modal component outside of the list and set it to visible on click of the list item. So you code will be something like this.
class YourComponent extends Component {
state = {
showModal: false,
};
render() {
const items = [1, 2, 3];
return (
<View>
<View>
{
items.map((item, i) => {
<Button key={i} onPress={() => this.setState({ showModal: true, item }) title="Open Modal" />
})
}
</View>
<ReactNative.Modal visible={this.state.showModal}>
<Text>{ this.state.item }</Text>
</ReactNative.Modal>
</View>
);
}
}

React native add active class when push the button

I have a 3 buttons on react native project iOS app. How can I set class active to clicked button and delete this class from others? Like addClass/removeClass that I had used on jquery?
First have your define your style "class".
const styles = StyleSheet.create({
btnSelected: {
...
},
notSelected : {
}
});
Then you can use a state property in your react component.
example :
state = {
btnSelected: 1
}
<Button
style={(this.state.btnSelected== 1)?styles.btnSelected:styles.notSelected}
onPress={() => this.setState({ btnSelected: 1 })} ... />
<Button
style={(this.state.btnSelected== 2)?styles.btnSelected:styles.notSelected} ...
onPress={() => this.setState({ btnSelected: 2 })} .../>
<Button
style={(this.state.btnSelected== 3)?styles.btnSelected:styles.notSelected}
onPress={() => this.setState({ btnSelected: 3 })} ... />
The key concept in React and React Native is, that you don't imperatively set the state of your UI. Instead, you change some state, and then declaratively render the UI based on that.
You could, for example use the local component state (this.state):
class Buttons extends React.Component {
state = {
activeButton: 'first'
}
render() {
return (
<View>
<Button
onPress={() => this.setState({ activeButton: 'first' })}
isActive={this.state.activeButton === 'first'}
/>
<Button
onPress={() => this.setState({ activeButton: 'second' })}
isActive={this.state.activeButton === 'second'}
/>
<Button
onPress={() => this.setState({ activeButton: 'third' })}
isActive={this.state.activeButton === 'third'}
/>
</View>
)
}
}
The onPress event handler sets local component state with setState, which causes the component to immediately re-render. The isActive property is then set on all the buttons based on the expression that compares this.state.activeButton with some value.