I would like to close the child component from the child when user click on the close button in child component. Tried to it by passing the state from the child back to the parent but it's not working. What have i done wrong here?
Parent
class Home extends Component {
constructor() {
this.state = {
visible: true
}
{
closeComponent = () => {
this.setState({
visible: false
});
}
render() {
return (
<Container>
{
this.state.visible &&
<Child closeComponent={this.closeComponent} />
}
</Container>
)
}
}
Child
import React from 'react';
import { Text, Image } from 'react-native';
import { View, Button } from 'native-base';
import styles from './ChildStyles.js';
export const Child = ({ closeComponent }) => {
return (
<View style={styles.Container}>
<Button style={styles.Btn} onClick={() => closeComponent}>
<Text style={styles.BtnText}>Close</Text>
</Button>
</View>
);
};
export default Child;
The syntax for arrow function in child is incorrect. Also native-base Button doesn't have an onClick but an onPress handler. It should be
<Button style={styles.Btn} onPress={() => closeComponent()}>
<Text style={styles.BtnText}>Close</Text>
</Button>
Related
I take photo to demonstrate, you may look at it:
My parent component is 1, grand child component place at 3, at 2 I can do some stuff because they is parent-child but I can't call function of 1 when I look from 3, any your interest, thanks!
you have to pass props from child to grandchild
here is an example (i use react native)
Parent.js
import React, { Component } from 'react';
import Child from './Child';
import { Button, Text, View } from 'react-native';
export default class Parent extends Component {
constructor(props) {
super(props);
this.state = {
result: 'original state'
}
}
stateUpdate(data) {
this.setState({result:data})
}
render() {
return (
<View>
<Text>parent state: {this.state.result}</Text>
<Button
onPress={() => this.stateUpdate('original state')}
title="original state"
color="darkgreen"
/>
<Child data={this.state.result} updateState={(data) => this.stateUpdate(data)} />
</View>
)
}
}
Child.js
import React, { Component } from 'react';
import GrandChild from './GrandChild';
import { Button, Text, View } from 'react-native';
export default class Child extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View>
<Text style={{height:20}} />
<Text>child prop: {this.props.data}</Text>
<Button
onPress={() => this.props.updateState('Changed from Child')}
title="change parent state"
color="#841584"
/>
<GrandChild data={this.props.data} updateParent={(data) => this.props.updateState(data)} />
</View>
)
}
}
GrandChild.js
import React, { Component } from 'react';
import { Button, Text, View } from 'react-native';
export default class GrandChild extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View>
<Text style={{height:20}} />
<Text>GrandChild prop: {this.props.data}</Text>
<Button
onPress={() => this.props.updateParent('change from GrandChild')}
title="change parent state"
color="darkblue"
/>
</View>
)
}
}
here is a snack
https://snack.expo.io/GsuAf65kK
or use context api.
hope it help.
I am trying to send value of TextInput to another Class Function in console.log. My approach is when the button is pressed the value FromStr in TextInput will got passed into another class function. Here's my code
import React, { Component } from "react";
import { StyleSheet, Text, View, TextInput, Button } from "react-native";
import receiveMessage from "./receiveMessage"
export default class WeatherProject extends Component{
constructor (props) {
super(props);
this.state={
From:'',
FromStr:'',
}
}
changeText=(From)=>{
this.setState({From})
}
changeText1=(To)=>{
this.setState({To})
}
onPress = ()=>{
this.setState({FromStr: this.state.From})
receiveMessage.receiveMessage();
}
render(){
return (
<View>
<View style={styles.inputFields}>
<TextInput placeholder="From" id="from" style={styles.fromField} onChangeText={this.changeText} />
<View style={styles.buttonStyle}>
<Button
title={"Go Back"}
color="#f194ff"
onPress={this.onPress}
></Button>
</View>
</View>
</View>
);
}
}
receiveMessage.js
import React, { Component } from "react";
export default class receiveMessage extends Component {
static receiveMessage=()=>{
console.log(this.state.FromStr)
}
}
React does not allow to pass the data between react components in this way.
Following is way to pass the data between components in React. To get more insights please follow
import React, { Component } from 'react';
class WeatherProject extends Component {
render() {
const messageToPassed = 'Hello';
return (
<div>
<ReceiveMessage message={messageToPassed} />
</div>
);
}
}
const ReceiveMessage = props => <h1>{props.message}</h1>;
export default App;
here we pass the value from sidemenu component by raising an event
App.js
class App extends React.Component {
handleSubmit = (e, data) => console.log(`my data from props`, data);
render() {
return (
<Sidemenu
onSubmit={(e, data)=>this.handleSubmit(e, data)} />
);
}
}
SideMenu.js
const Sidemenu = props => {
const { onSubmit} = props;
return (
<button onClick={(e, type)=>this.onSubmit(e, 'mydata')} />
);
}
Hello I have a problem with calling a function passed as prop at the child component. Im trying to replicate my code with only the relevant lines of code:
class Parent extends Component {
constructor(props) {
super(props)
this.press = this.press.bind(this)
}
press(param) {
console.log(param)
}
renderItem = ({item}) => (
<Child item={item} press={this.press} />
)
render() {
return (
<FlatList renderItem={this.renderItem} />
)
}
}
class Child extends PureComponent {
handlePress(param) {
// do some stuff
// call parent function
this.props.press(param)
}
render() {
const { id } = item
return <Button onPress={() => this.handlePress(id)} />
}
}
At the moment when pressing the button nothing happens, I got this already working with something like this:
<Child press={(param) => this.press(param)} />
however this causes performance issues.
How can I make this work ?
After a while of testing I came to this solution:
class Parent extends Component {
press = (param) => {
console.log(param)
}
renderItem = ({item}) => (
<Child item={item} press={this.press} />
)
render() {
return (
<FlatList renderItem={this.renderItem} />
)
}
}
class Child extends Component {
handlePress(param) {
// do some stuff
// call parent function
this.props.press(param)
}
render() {
const { id } = item
return <Button onPress={() => this.handlePress(id)} />
}
}
It can be a good solution: instead of passing reference from button to parent class, remove the button from child class and use TouchableOpacity instead.
import {
TouchableOpacity,
View,
} from 'react-native'
class Parent extends Component {
constructor(props) {
super(props)
}
press(param) {
console.log(param)
}
renderItem = ({item}) => (
<TouchableOpacity onPress={()=>{this.press(item.id)}}>
<Child item={item} />
</TouchableOpacity>
)
render() {
return (
<FlatList renderItem={this.renderItem} />
)
}
}
class Child extends PureComponent {
render() {
// just your view content
const { id } = item
return <View />
}
}
I have created a component called OrderGuideSelect and I am trying to render it in another area of our app. The problem is the OrderGuideSelect component is not rendering. When I set up breakpoints I am able to hit inside of the renderOrderGuideOptions function but it never makes it into the OrderGuideSelect.js file. I also tried putting 'export default' in front of the class declaration instead of the connection but it didn't make a difference. Does anyone know how to get the OrderGuideSelect component rendering properly?
Here is where I call the function that renders the OrderGuideSelect component:
<TouchableOpacity onPress={() => this.renderOrderGuideOptions()}>
<MBIcon name="ico-24-filter" size={30} style={styles.filterIcon}/>
</TouchableOpacity>
And here is the rendering function:
renderOrderGuideOptions = () => {
return (
<View>
<OrderGuideSelect />
</View>
)
}
Here is the OrderGuideSelect.js file:
import React, {Component} from 'react';
import {View, FlatList, ActivityIndicator, StyleSheet} from 'react-native';
import {connect} from 'react-redux';
import {fetchOrderGuides} from '../../actions/AppActions';
import {orderGuideSelected} from '../../actions/ProductAction';
import Header from '../../components/Header/Header';
import {createIconSetFromIcoMoon} from 'react-native-vector-icons';
import selection from '../../selection';
import OrderGuideOption from './OrderGuideOption';
const MBIcon = createIconSetFromIcoMoon(selection);
class OrderGuideSelect extends Component {
constructor(props) {
super(props);
}
componentWillMount() {
this.props.dispatch(fetchOrderGuides());
}
selectOrderGuide = id => {
this.props.dispatch(orderGuideSelected(id));
}
render() {
const {isLoading, orderGuides} = this.props.orderGuide;
return (
<View style={styles.wrapper}>
<Header />
<View style={styles.iconLine}>
<MBIcon name='ico-24-filter' style={styles.filterIcon} />
</View>
{isLoading &&
<ActivityIndicator
style={{alignSelf: 'center'}}
animating={true}
size='large'
/>
}
{!isLoading &&
<View style={styles.optionList}>
<FlatList
style={styles.optionList}
data={orderGuides}
keyExtractor={(item, index) => item.id.toString()}
renderItem={({item}) => <OrderGuideOption guideData={item} isSelected={item.id == this.props.selectedGuide.id} onSelected={this.selectOrderGuide} />}
/>
</View>
}
</View>
);
}
}
function mapStateToProps(state){
const {products, orderGuide} = state;
return {
selectedGuide: products.selectedOrderGuide,
orderGuide
}
}
export default connect(mapStateToProps)(OrderGuideSelect);
Also, I may be importing of the OrderGuideSelect component should be correct:
In your code calling this.renderOrderGuideOptions function on onPress event doesn't make sense, i.e. this.renderOrderGuideOptions returns the element but where to append it in DOM?
This should be achived using state in React. So you can set the state in onPress handler then use that state in render to show your OrderGuideOptions component.
So on onPress event bind the function handler:
<TouchableOpacity onPress={this.showOrderGuideOptions}>
<MBIcon name="ico-24-filter" size={30} style={styles.filterIcon}/>
</TouchableOpacity>
Now this showOrderGuideOptions will set the state named showOrderGuideFunction to true.
showOrderGuideOptions(){
this.setState({showOrderGuideFunction: true});
}
At last step use this showOrderGuideFunction state to render your component in the render function like this:
render() {
return (
<div>
...
{
this.state.showOrderGuideFunction &&
renderOrderGuideOptions()
}
</div>
)
}
You can do what you want probably holding a state property in your component and show your OrderGuideOptions according to this state property.
state = { showOrderGuideOptions: false };
renderOrderGuideOptions = () =>
this.setState( prevState => ( { showOrderGuideOptions: !prevState.showOrderGuideOptions }) );
render() {
return (
<View>
<TouchableOpacity onPress={this.renderOrderGuideOptions}>
<MBIcon name="ico-24-filter" size={30} style={styles.filterIcon}/>
</TouchableOpacity>
{ this.state.showOrderGuideOptions && <OrderGuideSelect /> }
</View>
)
}
I think you wanted to something similar to this
class RenderOrderGuideSelectComponent extends Component {
constructor(props) {
super(props);
this.state={
showOrderGuideSelect : false
};
}
renderOrderGuideOptions = () => {
this.setState({showOrderGuideSelect: true});
}
render() {
if(this.state.showOrderGuideSelect) {
return (
);
} else {
return (
this.renderOrderGuideOptions()}>
);
}
}
}
I have a mobile app which has components base structure. For showing Drawer globally i've implemented it in my Home.js like code below, but my drawer toggler must be in my Header component that inside my Container component.
How it possible to send instance of main drawer to Header component and control opening/closing status?
Home.js code:
class Home extends Component {
render() {
const drawerContent = <DrawerComp />;
return (
<Drawer
ref={comp => {
this.drawer = comp;
}}
drawerWidth={250}
drawerContent={drawerContent}
type={Drawer.types.Overlay}
drawerPosition={Drawer.positions.Right}
maskAlpha={0.05}
onDrawerOpen={() => {
console.log("Drawer is opened !");
}}
onDrawerClose={() => {
console.log("Drawer is closed !");
this.props.dispatch(displayDrawer());
}}
>
<Container>
<StatusBar barStyle="light-content" />
<Header drawer={this.drawer} />
<TouchableHighlight
underlayColor="#118d95"
onPress={this.handleDisplayDrawer}
>
<Text>Open Right Drawer</Text>
</TouchableHighlight>
</Container>
</Drawer>
);
}
}
Header component:
class Header extends Component {
handleDisplayDrawer = () => {
//
};
render() {
return (
<View style={styles.container}>
<TouchableHighlight
onPress={this.handleDisplayDrawer}
style={styles.colSmall}
underlayColor="#ffffff"
>
<Image
style={styles.icon}
resizeMode="contain"
source={require("./images/icon-menu.png")}
/>
</TouchableHighlight>
</View>
);
}
}
Pass function to Header component which calls that function when you want.
class Home extends Component {
toggleDrawer = () => {
this.drawer.toggle(); // edit this according to drawer library
}
render() {
<Header onMenuPress={this.toggleDrawer} />
}
}
class Header extends Component {
render() {
<TouchableHighlight onPress={this.props.onMenuPress}>
<Image />
</TouchableHighlight>
}
}
You can write a setDrawerState function in Drawer.js. that actually closes the drawer. Something like
setDrawerState(isOpen) => {
this.setState({
isOpen,
})
}
In Your home.js , you already have ref to drawer component .
you can write following function.
close = () => {
this.drawer.setDrawerState(false)
}
open = () => {
this.drawer.setDrawerState(true)
}
<Header
close={this.close}
open={this.open}
/>
I struggled alot to find a solution so, If you are using custom header component then my suggestion is to render customer header in each screen and toggle it using:-
navigation.openDrawer();