call Child component function from Parent Header Button - react-native

I Have two classes Parent class and the Child class and I want to call the Child class function from the Parent class. the problem is that I want to call the child class function from the Parent Header Button. I tried the refs method but didn't get the result. is there any other way to do it?
child class:
class FilterSlider extends React.Component {
constructor(props) {
super(props);
console.log(props);
}
PanelShow = () => {
this._panel.show();
};
render() {
return (
<SlidingUpPanel
ref={(c) => (this._panel = c)}
draggableRange={{ top: height / 1.2, bottom: -10 }}
animatedValue={this._draggedValue}
showBackdrop={false}
>
<View style={styles.panel}>
<View style={styles.panelHeader}>
<Text style={{ color: '#FFF' }}>Bottom Sheet Peek</Text>
</View>
<View style={styles.container}>
<Text>Bottom Sheet Content</Text>
</View>
</View>
</SlidingUpPanel>
);
}
}
export default FilterSlider;
and parent class:
class ReportsListView extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
this.props.navigation.setParams({
openSlider : this._openSlider
});
}
_openSlider() {
this.refs.child.PaenlShow();
}
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
return {
title : navigation.state.params.name,
headerLeft : null,
headerStyle : {
backgroundColor : '#4c8572'
},
headerRight : (
<View style={{ paddingLeft: 10, flexDirection: 'row' }}>
<TouchableOpacity onPress={() => params.openSlider()}> //from this icon i want to call the child PanelShow function.
<Icon name="arrow-left" size={30} color="#ffffff" />
</TouchableOpacity>
</View>
),
headerTitleStyle : {
flex : 1,
color : '#fff',
alignItems : 'center',
justifyContent : 'center',
fontWeight : 'bold'
}
};
render()
{
return(
<FilterSlider ref = 'child'/>
)
}
};

You're using ref property incorrectly. To fix this, you can try this:
Parent component
class ReportsListView extends Component {
componentWillMount(){
this.refs.child = null;
}
render() {
return (
<FilterSlider ref={(ref) => {
this.refs.child = ref
}}/>
)
}
}
Now, you can call your function from child component, e.g: this.refs.child.doSomethings().

Related

How to change text in sibling component in react-native?

I have an 'OutputBox' component and want to change the text being displayed in the component when I click a button.
I've read about props and state and i can't seem to get them working the way i need them too. I just started react-native and have a heavy background c++. I thought i could just declare a variable, 'text' in the 'OutputBox' component and then call a 'setOutputBoxText' function and change the 'text' var. Getters and Setters paradigm. I just cant wrap my head around how to use props to 'pass args' to components and the such.
export default class HelloWorldApp extends Component {
render() {
return (
<View style={{ flex: 1, alignItems: "flex-end" }}>
<CustomButton
text="N"
onPress={() => {
OutputBox.setOutputBox('You head North');
alert("You head North");
}}
/>
<OutputBox></OutputBox>
</View>
);
}
}
class CustomButton extends Component {
render() {
const { text, onPress} = this.props;
return (
<TouchableOpacity style={styles.buttonStyle}
onPress={() => onPress()}
>
<Text style={styles.textStyle}>{text}</Text>
</TouchableOpacity>
);
}
}
class OutputBox extends Component {
constructor( props ) {
super( props );
var displayText = 'Hello Traveller';
}
setOutputBox( newText ){
displayText = newText;
}
render() {
return (
<View style={ styles.outputBox }>
<Text>{this.displayText}</Text>
</View>
);
}
}
I would expect to be able to do something similar to what i have, however i just keep getting a typeError: OutputBox.setOutputBox is not a function. I know this is the wrong paradigm for react-native. I can't seem to wrap my head around doing something like this with props and state.
UPDATE: I no longer get the error typeError: OutputBox.setOutputBox is not a function. Now, the OutputBox just doesn't display anything. How I do I get the <Text/> component of the OutputBox to change and display.
Here is the correct way to do it.
export default class HelloWorldApp extends Component {
constructor( props ) {
super( props );
this.state={
displayText : 'Hello Traveller',
}
}
render() {
return (
<View style={{ flex: 1, alignItems: "flex-end" }}>
<CustomButton
text="N"
onPress={() => {
this.setState({displayText:'You head North'})
}}
/>
<OutputBox text={this.state.displayText}/>
</View>
);
}
}
class CustomButton extends Component {
render() {
const { text, onPress} = this.props;
return (
<TouchableOpacity style={styles.buttonStyle}
onPress={() => onPress()}
>
<Text style={styles.textStyle}>{text}</Text>
</TouchableOpacity>
);
}
}
class OutputBox extends Component {
render() {
return (
<View style={ styles.outputBox }>
<Text>{this.props.displayText}</Text>
</View>
);
}
}
I just removed the OutputBox component and put a <Text> component in there. I realized i didn't need the OutputBox component, since it's only purpose was to display text. This is what i ended up with
export default class HelloWorldApp extends Component {
constructor( props ) {
super( props );
this.state={
displayText : 'Hello Traveller',
}
}
render() {
return (
<View style={{ flex: 1, alignItems: "flex-end" }}>
<CustomButton
text="N"
onPress={() => {
this.setState({displayText:'You head North'})
}}
/>
<Text>{this.state.displayText}</Text>
</View>
);
}
}
class CustomButton extends Component {
render() {
const { text, onPress} = this.props;
return (
<TouchableOpacity style={styles.buttonStyle}
onPress={() => onPress()}
>
<Text style={styles.textStyle}>{text}</Text>
</TouchableOpacity>
);
}
}

How to access one control property in another control in ReactNative

I want to access this.state.sampleString from HelloWorldApp component
class to CustomWebView component class in react native, but in alert
this.props.sampleString showing 'undefined'.
Here is my code:
class CustomWebView extends Component{
constructor(props){
super(props);
this.state = { text: 'http://www.google.com' };
}
render() {
alert(this.props.sampleString);
return (
<WebView
source={{uri:this.state.text}}
style={{marginTop: 50}}
/>
);
}
}
export default class HelloWorldApp extends Component {
constructor(props) {
super(props);
this.state = { sampleString: 'http://www.google.com' };
this.getValue = this.getValue.bind(this);
}
getValue(){
//console.log(this.state.sampleString);
return this.state.sampleString
}
handleClick = () => {
alert(this.state.sampleString);
}
render(){
const {isFocused} = this.state;
const{onFocus,onBlur} = this.props;
return (
<View style={{
flexDirection: 'column',
height: '100%',
paddingTop: 36
}}>
<View style={{
flexDirection: 'row',
height : '5%',
width : '100%',
justifyContent: 'flex-start',
paddingBottom:3,
paddingTop:1,
marginTop : 20
}}>
<TextInput
selectionColor = {BLUE}
ref = "urltext"
underlineColorAndroid={isFocused?BLUE:LIGHT_GRAY}
onFocus = {this.handleFocus}
onBlur ={this.handleBlur}
style={styles.textInput}
onChangeText={(sampleString) => this.setState({sampleString})}
value={this.state.sampleString}
/>
<Button title="Submit"
onPress = {this.handleClick.bind(this)}
color="#9933ff"
accessibilityLabel="TestButton"/>
</View>
<CustomWebView/>
</View>
);
}
}
})
I need to change url in class CustomWebView on the onPress event of Button in
HelloWorldApp class. And that's why i want to access this.props.sampleString in CustomWebView class.
use CustomWebView like this
<CustomWebView
sampleString={this.state.sampleString}
/>
Please do it as following:
<CustomWebView
sampleString={this.state.sampleString}
/>
on CustomWebView, you should use the props - sampleString, not state variable - text.
class CustomWebView extends Component{
constructor(props){
super(props);
this.state = { text: 'http://www.google.com' };
}
render() {
alert(this.props.sampleString);
return (
<WebView
source={{ uri: this.props.sampleString }}
style={{ marginTop: 50 }}
/>
);
}
}
First of all, you are using the wrong method to update the state at onChangeText as,
onChangeText={(sampleString) => this.setState({sampleString})}
when you use above method you can get an error like,
sampleState is not defined
because you have to define which state you want to update with the updated value in setState method. You have to update state as,
onChangeText={(inputText) => this.setState({sampleString: inputText})}
And then you can pass this sampleString in CustomWebView as prop,
<CustomWebView uri = {this.state.sampleString} />
Finally, you can access this prop in CustomWebView as,
<WebView
source={{ uri: this.props.uri }}
style={{ marginTop: 50 }}
/>
And all done :)
Note: - Because you are updating state at onChangeText, and simultaneously passing this state as prop in CustomWebView. CustomWebView can access this state without button click.
you have to take two state variable. fist for textInput and second is for rendering Webview, which you have to pass in CustomWebView component.
Your HelloWorldApp class should be like following:
export default class HelloWorldApp extends Component {
constructor(props) {
super(props);
this.state = {
textInputData: 'http://www.google.com'
sampleString: 'http://www.google.com'
};
}
handleClick(){
//set sampleString when click on button
this.setState({
sampleString: this.state.textInputData
})
}
render(){
const {isFocused} = this.state;
const{onFocus,onBlur} = this.props;
return (
<View style={{
flexDirection: 'column',
height: '100%',
paddingTop: 36
}}>
<View style={{
flexDirection: 'row',
height : '5%',
width : '100%',
justifyContent: 'flex-start',
paddingBottom:3,
paddingTop:1,
marginTop : 20
}}>
<TextInput
selectionColor = {BLUE}
ref = "urltext"
underlineColorAndroid={isFocused?BLUE:LIGHT_GRAY}
onFocus = {this.handleFocus}
onBlur ={this.handleBlur}
style={styles.textInput}
onChangeText={(inputText) => this.setState({textInputData: inputText})}
value={this.state.textInputData}
/>
<Button title="Submit"
onPress = {this.handleClick.bind(this)}
color="#9933ff"
accessibilityLabel="TestButton"/>
</View>
<CustomWebView
sampleString={this.state.sampleString} />
</View>
);
}
} })
and you will get updated sampleString in componentWillReceiveProps() of CustomWebView component
class CustomWebView extends Component{
constructor(props){
super(props);
this.state = {
text: 'http://www.google.com'
};
}
componentWillMount(){
this.setState({ text:this.props.sampleString })
}
componentWillReceiveProps(newProps){
//when will you update url in textinput and do submit. you will get updated
sampleString here.
this.setState({ text:newProps.sampleString })
}
render() {
return (
<WebView
source={{uri:this.state.text}}
style={{marginTop: 50}}
/>
);
}
}

Using dynamic styles in react native

I've a couple of buttons in my react native app, on pressing any button, color should change. Code is as given below
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
TextInput,
Button,
TouchableHighlight,
Image,
Alert
} from 'react-native';
export default class Home extends Component {
constructor(props) {
super(props);
this.state= {
clicks: 0,
show: true,
isbuttonpress: false
};
}
onButtonState = () => {
this.setState({isbuttonpress: true});
}
render() {
return (
<View style={ [styles.container] }>
<Text style= { [styles.header] }>How likely is it that you would recommend this company to a friend or colleague?</Text>
<TouchableHighlight style = { [styles.buttonContainer, this.state.isbuttonpress?styles.gobackred:styles.goback] } onPress = { () => this.onButtonState() }>
<Text style = { styles.gobacktext }>0</Text>
</TouchableHighlight>
<TouchableHighlight style = { [styles.buttonContainer, this.state.isbuttonpress?styles.gobackred:styles.goback] } onPress = { () => this.onButtonState() }>
<Text style = { styles.gobacktext }>1</Text>
</TouchableHighlight>
<TouchableHighlight style = { [styles.buttonContainer, this.state.isbuttonpress?styles.gobackred:styles.goback] } onPress = { () => this.onButtonState() }>
<Text style = { styles.gobacktext }>2</Text>
</TouchableHighlight>
<TouchableHighlight style = { [styles.buttonContainer, this.state.isbuttonpress?styles.gobackred:styles.goback] } onPress = { () => this.onButtonState() }>
<Text style = { styles.gobacktext }>3</Text>
</TouchableHighlight>
<TouchableHighlight style = { [styles.buttonContainer, this.state.isbuttonpress?styles.gobackred:styles.goback] } onPress = { () => this.onButtonState() }>
<Text style = { styles.gobacktext }>4</Text>
</TouchableHighlight>
<TouchableHighlight style = { [styles.buttonContainer, this.state.isbuttonpress?styles.gobackred:styles.goback] } onPress = { () => this.onButtonState() }>
<Text style = { styles.gobacktext }>5</Text>
</TouchableHighlight>
<TouchableHighlight style = { [styles.nextContainer, styles.goback] } onPress = { () => this.onNextButtonState() }>
<Text style = { styles.gobacktext }>Next</Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
header: {
fontSize: 20,
alignItems: 'center',
padding: 20,
},
container: {
alignItems: 'center',
justifyContent: 'center'
},
buttonContainer: {
height:45,
justifyContent: 'center',
alignItems: 'center',
marginBottom:20,
width:45,
}, gobackred: {
backgroundColor: "#00a2b2",
},
goback: {
backgroundColor: "#00b5ec",
},
gobacktext: {
color: 'white',
},
nextContainer: {
height:45,
marginTop: 15,
justifyContent: 'center',
alignItems: 'center',
marginBottom:20,
width:250,
borderRadius:30,
}
})
Layout is as given below:
Whenever any option is selected, color of that button should change. But in my code, color of all buttons changes when clicked on any button. How can I fix it?
This happens because you used one state this.state.isbuttonpress for all button try to make the component of this code.
your TouchableHighlight Component
DemoButton.js
import React, { Component } from "react";
import { View, Text, TouchableHighlight } from "react-native";
export default class DemoButton extends Component {
constructor(props) {
super(props);
this.state = { isbuttonpress: false };
}
onButtonState = () => {
this.setState({ isbuttonpress: !this.state.isbuttonpress });
};
render() {
return (
<View>
<TouchableHighlight
style={{ backgroundColor: this.state.isbuttonpress ? "red" : "blue" }}
onPress={this.onButtonState}
>
<Text>{this.props.buttonTitle}</Text>
</TouchableHighlight>
</View>
);
}
}
App.js
import DemoButton from "./DemoButton";
export default class Heal extends Component {
constructor(props) {
super(props);
this.state = { isbuttonpress: false };
}
render() {
return (
<View>
<Header />
<DemoButton buttonTitle="0"/>
<DemoButton buttonTitle="1"/>
<DemoButton buttonTitle="2"/>
<DemoButton buttonTitle="3"/>
<DemoButton buttonTitle="4"/>
<DemoButton buttonTitle="5"/>
</View>
)
}
}

React Native - How to use a ref to set focus to an input when clicking on text

Here's what I'm doing:
export default class myComponent extends Component {
render() {
return (
<View>
<Text onPress={() => {this.input.focus()}}>Click Me</Text>
<Input ref={input => { this.input = input}}/>
</View>
)
}
}
I am using native-base components... not sure if that is affecting this.
When I press the Text component, I get an error stating: _this2.input.focus is not a function. (In '_this2.input.focus()', '_this2.input.focus' is undefined)
I don't use native-base, but at normal it should be like this:
import * as React from 'react';
import { Text, View, StyleSheet, TextInput, Dimensions } from 'react-native';
import { Constants } from 'expo';
const { width, height } = Dimensions.get('window');
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text onPress={() => {this.input.focus()}}>Click Me</Text>
<TextInput style={styles.input} ref={input => { this.input = input}}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
input: {
backgroundColor: '#bbb',
width: width - 40,
height: 40,
paddingHorizontal: 10,
paddingVertical: 5,
}
});
You can see the snacks here: https://snack.expo.io/#gasparteixeira/inputfocus
In case anyone comes across this stack overflow during the Hooks Era of React and React Native.
Solution with Hooks following the React Docs https://reactjs.org/docs/hooks-reference.html#useref
function TextInputWithFocusButton() {
const inputEl = useRef(null);
const onButtonClick = () => {
// `current` points to the mounted text input element
inputEl.current.focus();
};
return (
<>
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}
export default class myComponent extends Component {
public textInput: TextInput | null = null;
render() {
return (
<View>
<Text onPress={() => {this.textInput.focus()}}>Click Me</Text>
<TextInput ref={input => (this.textInput = input as any)}/>
</View>
);
}
}
export default class myComponent extends Component {
render() {
return (
<View>
<Text onPress={() => {this.input.focus()}}>Click Me</Text>
<Input ref={ref => (this.textinput= ref)}/>
</View>
)
}
}
and use this:
handleTextInput = () => {
this.textinput....
};

No transparent background in the navigated routing Component

I have a very basic app and I am using ex-navigation for navigation.
App.js (note the backgroundColor):
export default class App extends Component {
render() {
return (
<View style={{flex: 1, backgroundColor: 'lightblue'}}>
<TabEntry/>
</View>
);
}
}
TabEntry:
const Router = createRouter(() => ({
notification: () => Notification,
}));
const defaultRouteConfig = {
navigationBar: {
title: 'notify',
tintColor: 'blue',
backgroundColor: 'green',
},
};
export default class TabEntry extends React.Component {
render() {
return (
<NavigationProvider router={Router}>
<StackNavigation
initialRoute={Router.getRoute('notification')}
defaultRouteConfig={defaultRouteConfig}
/>
</NavigationProvider>
)
}
}
class Notification extends React.Component {
render() {
return (
<View>
<Text>NOTIFICATION!!!</Text>
</View>
)
}
}
Since, there is a backgroundColor in the parent Component, but no backgroundColor in its child component, it should have displayed a lightblue background. But instead the background is white. How can I make it transparent?
You could try putting a backgroundColor: 'transparent' in the <Text> style.
So do this:
<Text style={{backgroundColor: 'transparent'}}>NOTIFICATION!!!</Text>
https://github.com/facebook/react-native/issues/7964