How to make "condition for component" in react native - javascript

I want to make condition if this.props === "0", the component will show on screen and when else, the component will hide. How to make it?
I tried use react-native condition and doesn't work
this for my code:
{data.is_approved === '0' ? (
<TouchableOpacity
onPress = {() => this.deleteTrancation(data.id, data.sales_id)}
style={[styles.icons, common.backgroundWarn]}
>
<Icon name="clear" size={18} color={color.colorOff} />
</TouchableOpacity>
) : (
<Text style={[common.textValid]}></Text>
)}
my complete code: https://pastebin.com/U9p5akdi
I expect when string "0", the component will show and else, the component will hide

See whether if it works. May be you missed integer type as
string type
{data.is_approved === 0 ? (
<TouchableOpacity
onPress = {() => this.deleteTrancation(data.id, data.sales_id)}
style={[styles.icons, common.backgroundWarn]}>
<Icon name="clear" size={18} color={color.colorOff} />
</TouchableOpacity>
) : (
<Text style={[common.textValid]}></Text>
)}

its working for any condition 0 is string OR Number
{
data.is_approved == '0'
?
<TouchableOpacity/>
:
<Text style={[common.textValid]}></Text>
}

you shold pass some flag like ShowSecondComponent" to the second component from 1st component.
In your 1st component code
<Fragment>
Change renderSecond state of FirstComp {renderSecond && <SecondComp ShowSecondComponent ={this.state.renderSecond} />}
</Fragment
Receive the prop in second component and use it inside render method of second component with if.
class SecondComp extends Component {
render() {
if(!this.props.ShowSecondComponent) return null;
return <div>Rendering Second Component</div>;
}
}
Hope it helps

I have created a sample on codesandbox of working sample for you.
https://codesandbox.io/s/react-native-04dfj
FirstComponent
import React, { Component, Fragment } from "react";
import SecondComp from "./SecondComp";
class FirstComp extends Component {
state = {
renderSecond: true
};
render() {
const { renderSecond } = this.state;
return (
<Fragment>
Change renderSecond state of FirstComp {renderSecond && <SecondComp />}
</Fragment>
);
}
}
export default FirstComp;
Second Component
import React, { Component } from "react";
class SecondComp extends Component {
render() {
return <div>Rendering Second Component</div>;
}
}
export default SecondComp;
In the first component there is a state
state = {
renderSecond: true
};
You can change the renderSecond value to false and second component will not render.
Please check the link for working sample and you can even pass this value as prop from the parent component

Related

How to use HoC with React Native

I have an listing app where users can add items for multiple categories, when they want to add new record, there are 3 related screens with this particular feature. All of those screens have <Header/> component, so i thought HoC would be nice here so that i can reuse it across 3 screens.
However, i could not accomplish it.
Here is what i tried so far:
This is my HoC class
import React, { Component } from 'react';
import { View, StyleSheet, Text, StatusBar } from 'react-native';
import Header from '../components/Header';
const NewAd = (WrappedComponent) => {
class NewAdHoc extends Component {
handleBackPress = () => {
this.props.navigation.navigate('Home');
StatusBar.setBarStyle('dark-content', true);
}
render() {
const {contentText, children} = this.props
return (
<View style={styles.container}>
<Header
headerText={'Yeni ilan ekle'}
onPress={this.handleBackPress}
/>
<View style={styles.contentContainer}>
<Text style={styles.contentHeader}>{contentText}</Text>
<WrappedComponent/>
</View>
</View>
);
}
}
return NewAdHoc;
}
this is my screen:
class NewAdScreen extends Component {
render() {
const Content = () => {
return (
<View style={styles.flatListContainer}>
<ListViewItem />
</View>
);
}
return (
NewAdHoc(Content)
)
}
}
after that i am getting error
TypeError: (0 , _NewAdHoc.NewAdHoc) is not a function(…)
and i have no idea how can i fix it because this is my first time using hocs on a react-native app. I have looked why this error is popping and they suggest import components in this way:
import {NewAdHoc} from '../hocs/NewAdHoc';
but even this is not solved it.
any help will be appreciated, thanks.
The main purpose of a HOC is to encapsulate and reuse stateful logic across components. Since you are just reusing some jsx and injecting nothing in WrappedComponent you should be using a regular component here:
const NewAd = ({ contentText, children }) => {
handleBackPress = () => {
this.props.navigation.navigate('Home');
StatusBar.setBarStyle('dark-content', true);
}
return (
<View style={styles.container}>
<Header
headerText={'Yeni ilan ekle'}
onPress={this.handleBackPress}
/>
<View style={styles.contentContainer}>
<Text style={styles.contentHeader}>{contentText}</Text>
{children}
</View>
</View>
);
}
And use it like this
return(
<>
<NewAd>
<Screen1 />
</NewAd>
<NewAd>
<Screen2 />
</NewAd>
<NewAd>
<Screen3 />
</NewAd>
</>
)

Trigger onPress event on Child component within Parent component

I made a button component which I render in my Parent component. Been stuck for a while now on trying to fire a function on the onPress event of this child component that is used in my Parent.
I've been looking through some of the recommended questions and answers but I need some specific advice.
I simplified my code as much as possible, please have a quick look.
Thanks in advance!
// PARENT COMPONENT
export class Home extends Component {
constructor(props) {
super(props);
this.onPress = this.onPress.bind(this);
}
onPress = () => {
console.log("Hey");
};
render() {
return (
<View style={styles.container}>
<PrimaryButton text={"Sign up"} onPress={this.onPress} />
</View>
);
}
}
// CHILD COMPONENT
const PrimaryButton = ({ text }) => {
return (
<TouchableOpacity style={style.container} >
<Text style={style.text}>{text}</Text>
</TouchableOpacity>
);
};
export default PrimaryButton;
You need to pass onPress to TouchableOpacity as a prop. I don't know the props for TouchableOpacity but should be bound as either onPress or onClick. Event handlers always need to be passed to the root component (or as close to it as you can get, ie TouchableOpacity is from a 3rd party). Most, if not all, 3rd party components will have props for the proper events.
// CHILD COMPONENT
const PrimaryButton = ({ text, onPress }) => {
return (
<TouchableOpacity style={style.container} onClick={onPress} >
<Text style={style.text}>{text}</Text>
</TouchableOpacity>
);
};

React Conditional Render and Navbar

I am controlling what component should be shown on my applications screen via the state and a switch statement in the main render function. I am writing this in react-native but this is a react structure question.
I also have a Navbar component that I would ideally like to only rerender when the user clicks on a link in the Navbar itself, but I don't know of a great way to do this with how I have the switch statement setup now, it seems like I will have to rerender the Navbar every time depending on what condition is met by the state.
My question is, is there a way that I can still use conditional rendering of components in the render method like I am below AND have a component that is always rendered at the top of the screen like the Navbar? I know this is possible with things like React Router, but is there a better way to structure it without using a tool like React Router or having to rerender the NavBar component every time?
import React from 'react';
import GPS from './GPS/gps';
import Home from './Home';
import Photo from './Camera/Photo';
export default class App extends React.Component {
constructor() {
super();
this.state = {
hasCameraPermission: null,
type: Camera.Constants.Type.back,
currentView: null,
currentImage: null,
navigation: 'Overview'
};
this.updateNavigation = this.updateNavigation.bind(this);
}
updateNavigation(view) { //Update view function
this.setState({currentView: view});
}
render() {
const { currentView } = this.state;
switch(currentView) {
case null:
return (
<Home updateNav={this.updateNavigation} />
);
break;
case 'GPS':
return (
<View>
<GPS />
<Text onPress={() => this.setState({currentView: null})}>Back</Text>
</View>
);
break;
case 'Camera':
return (
<Photo updateNav={this.updateNavigation} />
);
break;
case 'viewPicture':
return (
<View>
<Image source={{uri: this.state.currentImage.uri}} style={{width: this.state.currentImage.width/10, height: this.state.currentImage.height/12}} />
</View>
);
break;
}
}
}
Always keep render as much as clean.
You can use && operator to do the same instead of using switch case. Use && operator and check every case and render accordingly. Check below code for better understanding.
render() {
const { currentView } = this.state;
return(
{currentView == null && (
<Home updateNav={this.updateNavigation} />
)}
{currentView == "GPS" && (
<View>
<GPS />
<Text onPress={() => this.setState({currentView: null})}>Back</Text>
</View>
)}
{currentView == "Camera" && (
<View>
<Photo updateNav={this.updateNavigation} />
</View>
)}
{currentView == "viewPicture" && (
<View>
<Image source={{uri: this.state.currentImage.uri}} style={{width: this.state.currentImage.width/10, height: this.state.currentImage.height/12}} />
</View>
)}
)
}

Click on a button don't display the WebView

I'm developing an app in react-native and i'm confronted to a problem:
I want that when i click on a button ( or directly the View where the button is ) a Webview is shown on screen and open the link directly passed in parameters.
But nothing happens.
Here is my code:
return (
<ScrollView style={[style.case1]} refreshControl={<RefreshControl refreshing={this.state.refreshing} onRefresh={this.handleRefresh} />} >
{
this.state.orders.map(function (order) {
let a = _this.getPosts(order);
let Final = _this.splitString(a.message," ");
return (
<View style={[style.case2]} key={a.message} >
<Couleur couleur={Final[4]} />
<Text style={[style.Nom]} >Nom : {Final[1]}</Text>
<Text style={[style.Nom]} >Numéro de build : {Final[2]}</Text>
<Button onPress={<Web url={Final[3]} />} title="Click"/>
</View>
);
})}
</ScrollView>
);
And the WebView class :
import React, {Component} from "react";
import {WebView} from "react-native";
export default class Web extends Component {
constructor(props){
super(props);
}
render() {
let uri = this.props.url;
return(
<WebView
ref={(ref) => {this.webview = ref;}}
source={{uri}}
style={{marginTop:20}}
/>
)
}
}
And i got this error :
"Object is not a function(evaluating 'this.props.onPress(e)')
I would be very happy if someone help me ! :)
The onPress action needs to be a function that does something. Right now, you are setting the action to a component and react doesn't know what to do with that.
Without some kind of navigation library controlling your views, you could do something like have the onPress set some state that controls a part of the render function that either shows your existing page or the new 'Web' component.
So make onPress like:
onPress={e => this.setState({showWebPart:true})}
Then in your current render function you could have a ternary like:
{this.state.showWebPart ? <Web url={Final[3]} /> : ..current render stuff}

How to make component re-render when value from outside changes?

So, I have simple code (class) like this:
export default class LoginAction {
isLoggedIn = () => {
return true
}
}
And I used it in my other classes like this:
export default class Main extends Component {
render = () => {
const loginAction = new LoginAction()
if (loginAction.isLoggedIn()) {
return (
<View style={{ flex: 1 }}>
<Header headerText={'Post List'} />
<PostList />
</View>
)
}
....... (split)
}
}
The question is, when I change the return value on the isLoggedIn function, why Main component not re-rendered?
It's React Native, and I use Hot Reloading.
A component re-renders only in 2 situations:
if its state has changed
if the received props have changed
In your Main component, none of these situations happen.
To fix it, you could pass isLoggedIn to your component:
// index.js
const loginAction = new LoginAction()
let isLoggedIn = loginAction.isLoggedIn()
const setLoggedUser = user => {
loginAction.setLoggedUser(user)
isLoggedIn = true
}
ReactDOM.render(
<div>
{!isLoggedIn && <Login setLoggedUser={setLoggedUser} />}
<Main isLoggedIn={isLoggedIn} />
</div>,
document.getElementById('root')
)
And use this prop in your component's render:
export default class Main extends Component {
render = () => {
if (this.props.isLoggedIn) {
return (
<View style={{ flex: 1 }}>
<Header headerText={'Post List'} />
<PostList />
</View>
)
}
...
}
}
In doing so, your component will re-render when isLoggedIn changes.

Categories