Use fat arrow function to change React.Component in React-Native - javascript

is it possible to render a React.Component over other React.Component using just fat arrow function, using state seems unnecessary in my case as there is no need to close the opened Component. I am trying to achieve the simplest to render a React.Component over other React.Component.
I am trying to do it like this:
<Button onPress={() => { return (<ShowOtherReactComponent/>); }} >Show OtherComponent</Button>
this is calling the <ShowOtherReactComponent/> I know that because I called an alert function from constructor but! nothing is rendering. why is that? how can I do this?
PS: this approach may be wrong, but still wanna see how it can be done. for science.

You shouldn't return jsx from your handlers. Usually to show and or toggle components conditional rendering is the way to go.
Instead of returning <ShowOtherReactComponent/> from onPress you conditionally render the component based on a boolean binded to the local state and change the state instead.
const Component = () =>{
const [show, setShow] = useState(false)
const onPress = () => setShow(true)
return(
<>
<button onPress={onPress}> Show </button>
{ show && <ShowOtherReactComponent/> }
</>
)
}

I've made an example to show what you could potentially do if you wanted a button to add components to display:
import React from 'react';
import autoBind from 'react-autobind';
export default class ButtonTest extends React.Component {
constructor(props) {
super(props);
this.state = {
extraComponents : []
};
autoBind(this);
}
addComponent() {
const newComponent = (<p>I'm a new component</p>);
this.setState({extraComponents: [...this.state.extraComponents, newComponent]})
}
render() {
return (
<div>
<button onClick={this.addComponent}>add component</button>
{this.state.extraComponent}
</div>
)
}
}
I've checked it and it works.

import React, { useState } from 'react'
import { SafeAreaView, View, Text, Button, Dimensions } from 'react-native'
const App = () => {
const [visibilityOfOtherView, setvisibilityOfOtherView] = useState(false)
const { height, width } = Dimensions.get('window')
const SCREEN_HEIGHT = Math.round(height)
const SCREEN_WIDTH = Math.round(width)
return (
<SafeAreaView style={{ height: SCREEN_HEIGHT, width: SCREEN_WIDTH, }}>
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: 'red' }}>
<Text style={{ marginBottom: 20 }}>
First Components
</Text>
<Button
title='Toggle Components View'
onPress={() => setvisibilityOfOtherView(!visibilityOfOtherView)}
/>
</View>
{
visibilityOfOtherView ?
<View style={{ height: SCREEN_HEIGHT, width: SCREEN_WIDTH, alignItems: 'center', justifyContent: 'center', backgroundColor: 'green' }}>
<Text style={{ marginBottom: 20 }}>
Secound Components
</Text>
<Button
title='Toggle Components View'
onPress={() => setvisibilityOfOtherView(!visibilityOfOtherView)}
/>
</View>
: null
}
</SafeAreaView>
)
}
export default App

Related

React Navigation 5: Fixing headerRight Spacing

This is what my header looks like now:
And this is what I am trying to achieve:
Code snippet:
<Stack.Navigator initialRouteName="MenuRoute">
<Stack.Screen
name={'MenuRoute'}
component={Menu}
options={({navigation, route}) => ({
headerTitle: () => (
<Text
style={{
...styles.headerTitle,
}}>
<Translatable value="Menu" />
</Text>
),
headerLeft: () => <AuthMenuPicker {...navigation} {...route} />,
headerRight: () => (
<View style={styles.row}>
<FacebookButton {...navigation} {...route}/>
<LanguagePicker />
</View>
),
headerStyle,
})}
/>
.....
.....
.....
</Stack.Navigator>
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
}
});
How can I move the Facebook Logo towards the right side (as shown in the image)?
I have tried marginLeft and paddingLeft but nothing seems to do the trick.
All help would be appreciated as I am new with this issue and with react navigation 5 in general.
UPDATE#1:
Added borderWidth:1 and borderColor: 'red' to clearly show the headerLeft area:
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
borderWidth: 1,
borderColor: 'red',
}
});
UPDATE#2 - Added component code snippets:
Code Snippet (FacebookButton component):
import React, { Component } from 'react';
import { StyleSheet } from 'react-native';
import { Button } from 'react-native-paper';
import Entypo from 'react-native-vector-icons/Entypo';
import {FACEBOOK} from '../constants';
class FacebookButton extends Component {
constructor(props) {
super(props);
}
componentDidMount() { }
render() {
return (
<>
<Button
//onPress={() => alert()}
onPress={() => {
this.props.navigate(
'FacebookMenuWebviewRoute',
{
url: FACEBOOK.FACEBOOK_PAGE,
},
);
}}
>
<Entypo
name="facebook"
size={this.props.iconSize || 25}
style={{ ...styles.icon, ...this.props.iconStyle }}
/>
</Button>
</>
);
}
}
export const styles = StyleSheet.create({
icon: {
color: 'white',
},
});
export default FacebookButton;
Code snippet (LanguagePicker component):
import React, {Component} from 'react';
import {StyleSheet} from 'react-native';
import {Menu, Button, withTheme} from 'react-native-paper';
import Fontisto from 'react-native-vector-icons/Fontisto';
import {IntlContext} from '../utility/context/Internationalization';
class LanguagePicker extends Component {
...
...
...
renderPicker() {
return (
<IntlContext.Consumer>
{(context) => {
return (
<Menu
visible={this.state.showMenu}
onDismiss={() => this.showMenu(false)}
anchor={
<Button
onPress={() => this.showMenu(true)}
style={{
...styles.menuButton,
...this.props.menuButtonStyle,
}}>
<Fontisto
name="earth"
size={this.props.iconSize || 25}
style={{...styles.icon, ...this.props.iconStyle}}
/>
</Button>
}>
{this.renderPickerItems(context)}
</Menu>
);
}}
</IntlContext.Consumer>
);
}
render() {
return <>{this.renderPicker()}</>;
}
}
export const styles = StyleSheet.create({
menuButton: {},
icon: {
color: 'white',
},
});
export default withTheme(LanguagePicker);
Thank you #GuruparanGiritharan for pointing out about the wrappers.
Solution:
Code snippet FacebookButton component:
<TouchableOpacity
style={{ justifyContent: 'center' }}
onPress={() => { ... }
>
<Entypo
name="facebook"
size={this.props.iconSize || 25}
style={{ ...styles.icon, ...this.props.iconStyle }}
/>
</TouchableOpacity>
New Header:
Explanation:
I was using Button component from react-native-paper and the component had its own fixed spacing. This caused the Facebook icon to be too spaced out.
Thus, removing the Button component and simply adding TouchableOpacity from react-native helped to reduce the space between the two icons on the header.

How to print the current value of a slider?

I am starting to learn sliders and other basic components in react native. I would like to print the current value of the slider in the terminal. I tried putting console.log() in different places, but didn't know what I was doing and got errors.
import React, { Component } from 'react';
import { Slider, View, Text } from 'react-native';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
sliderValue: "0",
};
}
render() {
return (
<View
style={{
flex: 1,
padding: 20,
justifyContent: "center",
backgroundColor: "#ecf0f1",
}}>
<Text style = {{ color: "black" }}>
Value of this slider is : {this.state.sliderValue}
</Text>
<Slider
maximumValue = {10}
minimumValue = {0}
step = {1}
value = {this.state.sliderValue}
onValueChange = {sliderValue => this.setState({ sliderValue })}
/>
</View>
);
}
}
Well, you have many options here, I'll give you 2.
You can just console log in your render method
render() {
console.log(this.state.sliderValue);
//the reset of your code
}
Or you can do it inline with the setState call
onValueChange = {sliderValue => console.log(sliderValue) || this.setState({ sliderValue })}

Passing onPress redirect to child component React Native

I am struggling a little bit. I have tried to create more components for my React native app but after I did it my ButtonSaving stoped redirecting to Dashboard for some reason. I was trying some ways to pass onRowPress to component but without luck. What do I do incorrectly here please?
Login button is working fine => redirecting to Dashboard
ButtonSaving not working at all => should redirect to Dashboard
AppNavigator.js
import { createStackNavigator } from 'react-navigation-stack'
import { createAppContainer } from 'react-navigation';
import Homepage from './components/Homepage/Homepage';
import Dashboard from './components/Dashboard/Dashboard';
const AppNavigator = createStackNavigator({
Homepage: Homepage,
Dashboard: { screen: Dashboard},
},
{
initialRouteName: 'Homepage',
defaultNavigationOptions: {
headerStyle: {
backgroundColor: 'white',
opacity: 70,
borderBottomColor: 'white',
borderColor: 'white'
},
headerTintColor: 'black',
headerTitleStyle: {
fontWeight: 'bold'
}
}
}
);
const Container = createAppContainer(AppNavigator);
export default Container;
Homepage.js
import React from 'react';
import { StyleSheet, Text, View, Button, Image } from 'react-native';
import {NavigationActions} from 'react-navigation';
// COMPONENTS
import ButtonSaving from './ButtonSaving/ButtonSaving';
class Homepage extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoading: false
},
this.handleClick = this.handleClick.bind(this);
this.onRowPress = this.onRowPress.bind(this);
}
handleClick() {
const counterApp = this.state.counter;
this.setState({
counter: counterApp + 1,
dashboard: 'Dashboard'
})
}
onRowPress = ({ navigation }) => {
this.props.navigation.navigate(this.state.dashboard);
}
render() {
return(
<View style={styles.container}>
{/* LOGIN BUTTON */}
<View style={styles.buttonContainer}>
<View style={styles.buttonLogin}>
<Button title="log in"
color="white"
onPress={() => this.props.navigation.navigate('Dashboard')}/>
</View>
</View>
{/* LOGO CONTAINER */}
<View style={styles.logoContainer}>
<Image
style={{height: 147, width: 170}}
source= {require('./REACT_NATIVE/AwesomeProject/logo.png')}
></Image>
</View>
{/* EXPLAINATION OF WALT */}
<Text style={styles.textContainer}>Lorem ipsum lorem upsum></Text>
{/* Needs to be refactored to VIEW */}
<ButtonSaving onPress={() => this.onRowPress}/>
</View>)
}
ButtonSaving.js
import React from 'react';
import { StyleSheet, Text, View, Button, Image, TouchableOpacity } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
class ButtonSaving extends React.Component {
constructor(props) {
super(props);
this.state = {
},
this.onRowPress = this.onRowPress.bind(this);
}
onRowPress = ({ navigation }) => {
this.props.navigation.navigate(this.state.dashboard);
}
render(){
return(
<View style={styleButton.container}>
<LinearGradient
colors={[
'#00b38f',
'#7dcf5a'
]}
style={styleButton.opacityContainer}>
<TouchableOpacity>
<Button
title="Start Saving"
color='white'
onPress={this.onRowPress}/>
</TouchableOpacity>
</LinearGradient>
</View>
)
}
}
const styleButton = StyleSheet.create({
container: {
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
width: '100%',
height: 50,
justifyContent: 'center',
marginTop: '39%'
},
opacityContainer: {
height: 48,
borderRadius: 25,
backgroundColor: 'darkgreen',
width: '70%',
justifyContent: 'center',
alignItems: 'center'
}
})
export default ButtonSaving;
You miss to put dashboard in your state in ButtonSaving.js
In Homepage.js when your are calling handleClick ?. Dunno how you got that working...
You say in the onRowPress this:
this.props.navigation.navigate(this.state.dashboard);
but I don't see anywhere that you set this.state.dashboard.
Probabbly you missed set it up.
It was simple refactor and this helped!
<ButtonSaving navigation ={this.props.navigation}/>
I will update solution for others later.
There is no point to save "dashboard" in the Homepage state or the ButtonSaving state.
In Homepage.js you don't need to pass onPress to ButtonSaving
...
<ButtonSaving navigation={this.props.navigation}/>
...
Next in ButtonSaving.js
onRowPress = () => {
this.props.navigation.navigate('Dashboard');
}

React native dynamic render

I'm trying to make a custom router component, that will pick a layout dynamically. But, when I'm trying to render layout dynamically I receive blank page.
What I'm doing wrong?
import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';
import WelcomePageLayout from '../layouts/welcome-page';
import GamePageLayout from '../layouts/game';
export default class Router extends Component {
constructor(props) {
super(props);
this.layouts = [
WelcomePageLayout,
GamePageLayout
];
this.state = {
currentLayout: 0
};
}
render() {
const layout = this.layouts[this.state.currentLayout];
return (
<View style={styles.container}>
{ layout }
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: 'column',
flex: 1,
paddingTop: 60,
alignItems: 'center',
justifyContent: 'center',
marginBottom: 100
}
});
A step ago, before adding this dynamic render everything was working as expected. So I'm pretty sure it's something about that.
Thanks in advance.
You are just passing the component as a child to View. Make sure you render it as well:
render() {
const Layout = this.layouts[this.state.currentLayout];
return (
<View style={styles.container}>
<Layout />
</View>
);
}

Add navigation to component onPress (React-Navigation)

In my app I have a FlatList component which renders the component below (effectively a row with small snippets of information), I'd like to have it so that I can click on each component within the FlatList which then takes the user to another screen which provides more details.
I've managed to make it so that each component is clickable and I can make it perform an alert() to show that it is clickable, but using React-Navigation is proving a tad tricky for me to add.
FlatList page:
/* #flow*/
import _ from 'lodash'
import {getAllQuestions} from './questionRepository'
import ProfilePicture from './components/ProfilePicture'
import QuestionerAndQuestion from './questionRow/QuestionerAndQuestion'
import Separator from './components/Separator'
import {Button, FlatList} from 'react-native'
import React, {Component} from 'react'
export default class QuestionList extends Component {
static navigationOptions = ({navigation}) => ({
title: 'AIBU',
headerRight: (
<Button
onPress={_.debounce(() => {
navigation.navigate('Add')
}, 500)}
title="Add"
/>
),
headerStyle: {
backgroundColor: 'rgb(245, 245, 245)',
},
headerLeft: <ProfilePicture size={'small'} />,
})
state = {questions: []}
componentDidMount() {
this.getData()
}
async getData() {
const questions = await getAllQuestions()
this.setState({questions})
}
render() {
return (
<FlatList
ItemSeparatorComponent={Separator}
data={this.state.questions}
renderItem={({item}) => <QuestionerAndQuestion item={item} />}
/>
)
}
}
QuestionerAndQuestion component:
/* #flow */
import ProfilePicture from '../components/ProfilePicture'
import React from 'react'
import TextContainer from './TextContainer'
import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native'
const styles = StyleSheet.create({
row: {
backgroundColor: 'rgb(255, 255, 255)',
height: 125,
flex: 1,
flexDirection: 'row',
},
profilePic: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
flexDirection: 'row',
},
textBody: {
flex: 6,
},
})
const QuestionerAndQuestion = ({item}: {item: Object}) =>
<TouchableWithoutFeedback onPress={() => navigate would go here?}>
<View style={styles.row}>
<View style={styles.profilePic}>
<ProfilePicture />
</View>
<View style={styles.textBody}>
<TextContainer item={item} />
</View>
</View>
</TouchableWithoutFeedback>
export default QuestionerAndQuestion
I assume you navigated to the QuestionList component, therefore, you have the navigation object on there. What you would want to do is pass the navigation down to the QuestionerAndQuestion as a prop and then you can access it from onPress as a prop.
Something like this:
<QuestionerAndQuestion item={item} navigation={this.props.navigation} />
Hope this helps
This solved my issue.
Within QuestionList
render() {
const navigation = this.props.navigation
return (
<FlatList
ItemSeparatorComponent={Separator}
data={this.state.questions}
renderItem={({item}) =>
<QuestionerAndQuestion item={item} onPress={() => navigation.navigate('Question')} />}
/>
)
}
Within QuestionerAndQuestion
const QuestionerAndQuestion = ({item, onPress}: {item: Object, onPress: Object}) =>
<TouchableWithoutFeedback onPress={onPress}>

Categories