I am trying to open modal from the child component - react-native

I have tried many ways but non of these worked. I am trying from 5 days.
I used redux,props,then ref . Non of these helped.
I need the modal to be visible when I call it from another class.
// this is the parent class
export default class Search1 extends React.Component {
constructor(props) {
super(props);
this.setModalVisible1 = this.setModalVisible1.bind(this);
this.state = {
modalVisible1: false,
};
this.closeModal = this.closeModal.bind(this);
}
setModalVisible1(visible) {
this.setState({ modalVisible1: visible });
// this.setModalVisible2(visible);
}
closeModal() {
console.log("modalvi1 value is in closemodal ", this.state.modalVisible1);
this.setState({ modalVisible1: false });
}
render() {
return (
{/* it renders the screen again when I call the */}
<Modal
closeModal={() => this.closeModal}
animationType="slide"
transparent={true}
visible={this.state.modalVisible1}
</Modal>
<NavStack />
);
}
}
// this is the child class
class HomeScreen extends React.Component {
render() {
<TouchableOpacity
style={styles.firstStyle}
onPress={() => {
this.props.closeModal();
);
}}
>
return (
}
The modal should be visible when called from outer child class. It needs to be close when called from the parent class.
I tried using redux. that does not worked. Then I used props. Then I used the ref. None of these helped. Just get tired of this. Help me out of this.

Pass the function to modal
closeModal() {
this.setState({ modalVisible1: false });;
}
<Modal
closeModal={this.closeModal}
animationType="slide"
transparent={true}
visible={this.state.modalVisible1} />
and run it on child component as this.props.closeModal()

Related

Navigation inside react-native-modal

I have an app with bottom tab navigation (in case it's important) and sometimes user can open a modal (react-native-modal). There are buttons in the modal and I want to implement navigation inside the modal so that when the user presses one of the buttons they are navigated to another screen INSIDE the modal (and can navigate back).
Any help is appreciated, thanks in advance!
The example of what I want:
I had one problem like this. But I didn't made it with route, because I'm in a route and I would like to open another component inside screen.
So I did it using pure component. I did an control visibility variable, and the other "screen" was showed when user click on button, and hided when user closes it.
Here is an example:
//Parent component
class Parent extends Component {
state = {
viewClhild: false
}
goToChild = (task) => {
this.setState({viewChild: true})
}
onShowClhildChange(viewChild) {
this.setState({ viewChild });
}
render() {
<View>
{
this.state.viewChild
? <ChildScreen onShowClhildChange={this.onShowClhildChange.bind(this)} />
: <Text>Show Parent</Text>
}
<Button
onPress={() => {this.goToChild()}}
>
<Text style={button.text}>Entrar</Text>
</Button>
</View>
}
}
//Child Component
class ChildScreen extends Component {
isChildVisible = (isVisible) => {
this.setState({ viewChild: isVisible })
if (this.props.onShowClhildChange) {
this.props.onShowClhildChange(isVisible);
}
}
constructor (props) {
super(props);
this.state = {
viewChild: this.props.viewChild
}
}
render() {
return (
<View>
<Button
onPress={() => this.isChildVisible(false)}
>
<Text>CLOSE CHILD SCREEN</Text>
</Button>
</View>
)
}
}
I hope it can help you!

How can I call setState from a different class that is in the same file but different class?

I call a function that is in my Homepage class from my ProfileScreen class that is in the same .js file. I successfully did that, but in that function a setState is called, and when the function is called from the other class, the state doesn't change. How can I get this.state.user in HomePage to change from calling the onPressLogout function in the ProfileScreen class?
export default class HomePage extends Component<Props> {
state = {
email:'',
password:'',
firstname:'',
lastname:'',
user:true,
error: '',
}
onPressLogout(){
firebase = require('firebase');
firebase.auth().signOut()
.then(() => this.setState({
user:false
}))
.catch(() => this.setState({
error: 'Logout Failure',
}))
}
render(){
return <AppContainer>
</AppContainer>;
}
}
class ProfileScreen extends React.Component {
constructor(props) {
super(props);
Obj = new HomePage();
}
render() {
return (
...
<TouchableOpacity style={styles.button} onPress =
{()=>Obj.onPressLogout()}>
</TouchableOpacity>
...
}
}
const TabNavigator = createBottomTabNavigator({
Profile: ProfileScreen,
});
const AppContainer = createAppContainer(TabNavigator);
I get this warning when I run the code and the this.state.user doesn't change:
Warning: Can't call "setState" on a component that is not yet mentioned.
You should pass the function of the parent element into the child element as a prop. Then, you can call it in the child to manipulate the state of the parent class.
Here is an example,
class ChangeButton extends React.Component{
render(){
return (
<Button title="Change" onPress={this.props.updateMainState}/>
)
}
}
export default class App extends React.Component {
state = {
name: 'Fatih'
}
changeName = ()=> {
this.setState({
name: 'Faruk'
})
}
render() {
return (
<View style={styles.container}>
<Text>
{this.state.name}
</Text>
<ChangeButton updateMainState={this.changeName}/>
</View>
);
}
}
In the code above, we passed changeName function into the ChangeButton element. The Button in ChangeButton calls the function of the parent element when you press it, which manipulates the state of the main class.
Here is the working code: ProjectLink

How to make every React Component reload based on selected value of picker?

How can I force reload certain or all react Components when a particular value is selected using Picker?
import React from 'react';
import { Picker, Text, View } from 'react-native';
export default class Test extends React.Component {
render(){
return (
<View>
<TestComponent />
<Text>
{defaultKey + ' from defaultKey from main class'}
</Text>
</View>
);
}
}
let myArr = [
{
"key": "key0",
"value": "value0"
},
{
"key": "key1",
"value": "value1"
}
];
let defaultKey = "key0";
class TestComponent extends React.Component {
constructor (props){
super(props);
this.state = {
selectedValue : "value0",
PickerValueHolder : "value0"
}
}
render(){
return (
<View>
<Picker
selectedValue ={ this.state.PickerValueHolder }
onValueChange ={ (itemValue, itemIndex) => {
this.setState({ PickerValueHolder: itemValue });
defaultKey = myArr[itemIndex].key;
defaultIndex = itemIndex;
}
}
>
{ myArr.map((item, key)=>(
<Picker.Item label={ item.key } value={ item.value } key={ key } />)
)}
</Picker>
<Text>
{defaultKey + ' from defaultKey from TestComponent'}
</Text>
</View>
);
}
}
In this case, the <Text> in the default class is not reloading. How do I make it reload? And how can I force reload Imported components as well?
React Components renders / refresh whenever state / props changes. If you want to re render current component change it's state. If you want to render the child component change it's props. If you want to re render the parent component use a callback and modify the state in callback.
You could use global state management like redux, but if you're unfamiliar with that, you can send a handler into the Test Component as a callback to the Parent via the props.
Changing current component value use
this.state
Changing a child component value use and pass the prop in by
Inserting Props to child:
<ChildComponent prop1={value}/>
Getting the value from the child component:
this.props.prop1
Updating the Parent state is similar to the Above but requires the prop to be a function passed from the parent.
handler () {// some function in parent component}
<ChildComponent prop1={this.handler}/>
It would mean it would look something like below:
import React from 'react';
import { Picker, Text, View } from 'react-native';
export default class Test extends React.Component {
constructor(props) {
super(props)
this.handler = this.handler.bind(this);
this.state = {
defaultKey : "somevalue"
};
}
handler(value) {
this.setState({
defaultKey: value
})
}
render(){
return (
<View>
<TestComponent handler={this.handler}/>
<Text>
{this.state.defaultKey + ' from defaultKey from main class'}
</Text>
</View>
);
}
}
let myArr = [
{
"key": "key0",
"value": "value0"
},
{
"key": "key1",
"value": "value1"
}
];
let defaultKey = "key0";
class TestComponent extends React.Component {
constructor (props){
super(props);
this.state = {
selectedValue : "value0",
PickerValueHolder : "value0"
}
}
render(){
return (
<View>
<Picker
selectedValue ={ this.state.PickerValueHolder }
onValueChange ={ (itemValue, itemIndex) => {
this.setState({ PickerValueHolder: itemValue });
defaultKey = myArr[itemIndex].key;
defaultIndex = itemIndex;
this.props.handler(defaultKey);
}
}
>
{ myArr.map((item, key)=>(
<Picker.Item label={ item.key } value={ item.value } key={ key } />)
)}
</Picker>
<Text>
{defaultKey + ' from defaultKey from TestComponent'}
</Text>
</View>
);
}
}
UPDATE:
The OP has asked about why to use redux (as some of the components are not nested through the Test class.
What is redux?
Redux is a predictable state container for JavaScript apps.It helps you write applications that behave consistently.
Check out the docs here: https://redux.js.org/
Essentially, you've entered an issue a lot of people face when building an application that needs to share state between components in React/React Native. In every component you have a local state (this.state) - Redux includes a global App State, therefore in your classes where you change your default value, you can update the global store (which all components have access to). The value which you display the defaultValue would be from the global store.
Essentially, components which are not related to each other, will not know about each others state you'll need to use a global store such as redux. I suggest you do some research on the best technique for you. One way you could achieve it at present would be to wrap the whole application in a parent component and pass the props down from there, such as
-- ParentComponent (set state here)
-- ChildComponent1 (Pass Props)
-- ChildComponentOf1 (Pass Props)
-- ChildComponent2 (Pass Props)
For some further reading check out some posts here:
How to update parent's state in React?
How to share state among multiple scenes of a Navigator in React-Native

passProps not setting props for ListItem for react-native

I am using a ListItem onPress to navigate to a different route using the code below.
onPress(item) {
this.props.navigator.push({
component: Areas,
passProps: {
new_id: item.new_id,
}
});
}
_renderItem(item) {
return (
<ListItem item={item} onPress={ () => this.onPress(item) }/>
);
}
However, the this.props.new_id is undefined in the next component.
export default class areas extends Component {
constructor(props) {
super(props);
console.log(" UUUU ");
console.log(this.props.new_id);
}
render(){
return (
<Text style={styles.liText}>AAA {this.props.new_id} BBB</Text>
);
}
AppRegistry.registerComponent('areas', () => areas);
Is there anything I am doing incorrectly?
Actually, I found the answer. I looked in renderScene which was not passing the props properly.
I fixed it in the following way:
Initial:
return React.createElement(route.component, { navigator });
To:
return React.createElement(route.component, { ...this.props, ...route.passProps, route, navigator } )
This seems the pass the props.

React native android modal visible is set to false but still showing

I have set modal visibility to false but it still showing. I cant figure out what causes this issue. Maybe somebody had this problem before ?
export default class Controls extends Component {
constructor(props) {
super();
this.state = {
modalVisible: false,
}
}
render() {
return (
<Modal
animationType={'slide'}
modalVisible={this.state.modalVisible}
>
</Modal>
);
}
}
The prop that controls the visibility of the modal is visible and not modalVisible.
Hence the correct code would be:
export default class Controls extends Component {
constructor(props) {
super();
this.state = {
modalVisible: false,
}
}
render() {
return (
<Modal
animationType={'slide'}
visible={this.state.modalVisible}
>
</Modal>
);
}
}