How to change text in sibling component in react-native? - 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>
);
}
}

Related

Passing param to route React native

I'm trying to pass a param to a new screen in order to display it. my object is in a fetched data of array that i display using map, the code looks like this:
<Text > Show:</Text>
{
this.state.data.map((item, i) => {
//Show only two dates
return (i < 2) ?
<View>
<Text>{moment(item[0]).format("ddd DD/MM")}</Text>
<View style={{ flex: 1, flexDirection: 'row' }}>
{
item[1].map((day, i) => {
//show only 3 times
return (i < 3) ?
<TouchableOpacity onPress={() => NavigationService.navigate('myScreen',//what should i wright here!>
<Text>{moment(day.date_start).format("h:mm a")}</Text> // i want to pass this displayed text {moment(day.date_start).format("h:mm a")}
</TouchableOpacity>
:
<></>
})
}
</View>
</View>
: <></>
})
}
so as you can see i want to pass {moment(day.date_start).format("h:mm a")} to myScreen and display it, but i can't figure out how.
myScreen code is simple:
class Myscreen extends React.Component {
render() {
return (
<Text> display it here! </Text>
i would appreciate some help.thank you
In your first screen, you have to pass the text like this...
<TouchableOpacity onPress={() => this.props.navigation.navigate('myScreen', { text: moment(day.date_start).format("h:mm a") })}>
<Text>Press me</Text>
</TouchableOpacity>
In your myScreen, you have to receive it like this...
class Myscreen extends React.Component {
constructor(props) {
super(props);
}
render() {
const text = this.props.route.params.text;
return (
<Text>{text}</Text>
)
}
}
Please make sure that you are using #react-navigation/stack": "^5.x.x

call Child component function from Parent Header Button

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().

Unexpected token, expected; When calling a function in react native

I am trying to call a function when a button is pressed.
After I add the function, it errors out with the Unexpected token error.
I followed instructions from all previous similar questions but it doesn't solve my case. Please help.
_handlePress: function() {
console.log("Butto GO!")
}
export default class fun extends Component {
render() {
return (
<View style={styles.container}>
<TouchableHighlight onPress={() => this._handlePress()}>
<Image style={{width: 50, height: 50}} source={require('./go.png')} />
</TouchableHighlight>
</View>
);
}
}
Also, Should the called function be defined before the default class?
Put the function behind render, after the class and I don't know if u do test : function() it works there so try my example and give feedback
export default class fun extends Component {
_handlePress() {
console.log("Butto GO!")
}
render() {
return (
<View style={styles.container}>
<TouchableHighlight onPress={() => this._handlePress()}>
<Image style={{width: 50, height: 50}} source={require('./go.png')} />
</TouchableHighlight>
</View>
);
}
}
or if you want to do behind the export class you can use _handlePress() instead of this._handlePress() and it should work!
Example:
'use strict';
import React, {Component} from 'react';
import {View,Text,TouchableOpacity,Alert,Dimensions} from 'react-native';
const windows = Dimensions.get('window');
export default class Feed extends Component {
_test(){
Alert.alert("Test");
console.log("It worked!");
}
render() {
return (
<View style={{flex: 1}}>
<TouchableOpacity onPress={() => this._test()}>
<Image source={require('../image/2.jpg')} style={{height: windows.height, width: windows.width, }} />
</TouchableOpacity>
</View>
);
}
}

state property undefined in render function

In the render function on one of my views I am trying to have the opacity of a view be tied to a state property: this.state.infoOpacity.
This is turning an error "undefined is not an object (evaluating 'this.state.infoOpacity')"
Any guidance would be helpful.
export default class BookView extends Component
{
constructor(props) {
super(props);
this.state = {
hideInfo:false,
infoOpacity:0.80,
swiperWidth:Dimensions.get('window').width,
swiperHeight:Dimensions.get('window').height
};
}
render() {
pages.forEach(function(ranPage){
photoViews.push(
<View key={ranPage.letter} style={{width: Dimensions.get('window').width, height: Dimensions.get('window').height}}>
<View style={[styles.meow,{opacity: this.state.infoOpacity}]}>
<Text style={styles.text}>{ranPage.name}</Text>
<Text style={styles.text}>{ranPage.phonetic}</Text>
<Text style={styles.text2}>{ranPage.description}</Text>
</View>
</View>
)
});
return (
<View style={{flex:1}}>
<Swiper showsButtons={false} style={{backgroundColor:'#000'}} width={this.state.swiperWidth} height={this.state.swiperHeight}>
{photoViews}
</Swiper>
</View>
);
}
}
The context changed in your forEach function. Use an arrow function to fix your issue. So instead of
pages.forEach(function(ranPage){ ... });
write this
pages.forEach((ranPage) => { ... });

React Native - Error navigating to child components

I am able to define the initial route(Home) and the app navigates to that route. Inside Home I am calling another component called BoxLists which is displayed as expected. The issue I am having is when calling another component called StationOne from inside BoxLists.
I am getting the following error: uncaught error: undefined is not an object (evaluating 'this.props.navigator.push'
So the question is: How can I navigate from BoxLists to StationOne?
Note: I am planning to navigate to additional components(StationOne, StationTwo, StationN+1) from BoxLists.
Here is the code although you can go to RNPlayground at https://rnplay.org/apps/rLB5HQ. Thanks!
class App extends React.Component {
navigatorRenderScene(route,navigator){
if (route.title == "Home")
{
return( <Home navigator={navigator} /> );
}
if (route.title == "StationOne")
{
return( <StationOne navigator={navigator} /> );
}
}
render() {
return (
<Navigator
initialRoute = {{ title: "Home" }}
renderScene = {this.navigatorRenderScene.bind(this)}
/>
);
}
}
class Home extends React.Component {
render() {
return (
<View style={{flex: 1}}>
<View style={styles.header}>
<Text style={styles.headerText}>AdView</Text>
</View>
<BoxLists author="station one" navigator={navigator} />
</View>
);
}
}
class BoxLists extends React.Component {
_goToStation(){
this.props.navigator.push({
title: 'StationOne'
});
}
render() {
return (
<View>
<Text>You are in BoxList. The passed prop is: {this.props.author}</Text>
<TouchableHighlight onPress={this._goToStation.bind(this)}>
<Text>Press here to go to StationOne</Text>
</TouchableHighlight>
</View>
);
}
}
class StationOne extends React.Component {
render() {
return (
<View style={{flex: 1}}>
<Text> This is station one </Text>
</View>
);
}
}
class Home extends React.Component {
render() {
return (
<View style={{flex: 1}}>
<View style={styles.header}>
<Text style={styles.headerText}>AdView</Text>
</View>
<BoxLists author="station one" navigator={this.props.navigator} />
</View>
);
}
}
You need to pass this.props.navigator for the BoxLists component as shown above