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}
Related
I'm trying to create a custom component and put other components like or inside this component but it doesn't seem to be working (nothing shows up). Could someone be kind enough to provide an answer or perhaps correct my understanding where it's gone wrong?
For example, if I have a Home page and inside there's a Card component where within there's Text and View components.
import React from 'react'
import {Text, View} from 'react-native'
const CoolCard = ({props}) => {
return(
<View>
{props}
</View>
)
}
const Home = () => {
return(
<View>
<CoolCard>
<Text>This is a cool card!</Text>
</CoolCard>
</View>
)
}
export default Home
This doesn't work but if I do
const Home = () => {
return(
<View>
<CoolCard props = {
<Text>This is a cool card!</Text>
}/>
</View>
)
}
this works, which I understand. Is there a way for me to write the first example to make it work?
Thanks a lot!
You should use the 'children' prop to get the children
const CoolCard = ({children}) => {
return(
<View>
{children}
</View>
)
}
const Home = () => {
return(
<View>
<CoolCard>
<Text>This is a cool card!</Text>
</CoolCard>
</View>
)
}
export default Home
In order to "wrap" a component inside another you can use props.children this is how it looks in a react functional component :
Wrapper component:
const WrapComponent = ({children}) => (
<Text>
{children}
</Text>
)
Then you can wrap it around any valid JSX:
<WrapComponent> {/* put stuff here */} </WrapComponent>
You can find more in the official react documentation
Suppose I'm making a gallery-like app where you can view a list of images in a long strip. This seems simple enough but I'm encountering a problem where these images are loaded at the same time and (my guess) is that these images are behind some sort of DDoS protection service which prevents me from loading them all at the same time (It gave me 403 errors).
So my solution would be to load them one by one sequentially, however I'm not sure how this could be done in React as I'm quite new to React/React Native in general and communications between sibling components and/or child-parent aren't very straight forward. I've read up on Redux and could this be the solution? - But I've still not got the clear picture on how this can be done either.
For example this is what I have which isn't working
class Gallery extends React.Component {
...
renderPage(page) { //Each Images
return (<Page image={page.item} />)
}
...
render () {
return (
<Container>
<Header />
<Content>
{ this.state.isLoading ? <Spinner /> : (
// this loads all images at the same time which causes error
<FlatList
initialNumToRender={2}
data={this.state.pageArray}
renderItem={this.renderPage}
keyExtractor={(item, index) => index}
/>
)}
</Content>
</Container>
);
}
}
export default Gallery;
I have tried this on my own, Maybe it will help you a bit.
import React, {Component} from 'react';
import {Text, FlatList} from 'react-native';
class Gallery extends Component {
state = {
pageArr: [{name: 'abc'}, {name: 'def'}, {name: 'ghi'}],
isLoading: false,
};
renderPage(page) {
return <Text>{page.name}</Text>;
}
render() {
const {isLoading, pageArr} = this.state;
return isLoading ? (
<Spinner />
) : (
<FlatList
data={pageArr}
renderItem={({item}) => this.renderPage(item)}
keyExtractor={(item, index) => index}
/>
);
}
}
export default Gallery;
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
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>
);
};
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>
)}
)
}