if statement in render method - react native - react-native

i would like to use if statement in the return of render method , what i mean is something like this :
export default class App extends Component
{
render()
{
return(
<View>
if(this.state.error)
{
<View>
<Image source={{"error"}} />
<Text>An Error Happen</Text>
</View>
}
else
{
<View>
<List dataArray={this.state.items}></List>
</View>
}
</View>
);
}
}
i can use ternary operator , but what i want is to use if statement if it possible

Background
What is the difference between a statement and expression
Specific to JavaScript:
What is the difference between an expression and a statement in JS?
JavaScript: declarations vs expressions vs statements
return expects an expression as the argument. if statements are not expressions (makes sense, since statement is in the name).
The implementation details of JSX (that stuff with <Tags>, but in javascript) is also relevant. JSX is compiled into normal JavaScript.
<MyButton color="blue" shadowSize={2}>
Click Me
</MyButton>
compiles to
React.createElement(
MyButton,
{color: 'blue', shadowSize: 2},
'Click Me'
)
documentation.
If you want to evaluate a JavaScript expression in JSX you need to enclose it in curly braces.
const myButtonColor = 'blue'
//...
<MyButton color={myButtonColor} shadowSize={2}>
Click Me
</MyButton>
Back to the Question
Ways of accomplishing if-like functionality:
inline logical and (&&)
ternary operator (?)
return in if/else statements
Let's look at some examples:
Inline Logical And
render() {
return (
<View>
{this.state.error && <Text> There's an error! </Text>}
</View>
)
}
This method is the simplest and I recommend trying it first. It makes sense when you don't want to do anything if the condition evaluates to false. && behaves a bit different in javascript than in other languages. When this.state.error evaluates to false, render returns this.state.error, which may have unintended consequences if this.state.error happens to be the empty string or 0.
Ternary Operator
render() {
return (
<View>
{this.state.error ? <Text>Error!</Text> : <Text>No Error!</Text>}
</View>
)
}
The biggest problem with this is that the lines get long pretty quickly. You can get around this with parentheses.
render() {
return (
<View>
{this.state.error ? (
<Text>Long, detailed error message</Text>
) : (
<Text>No Error!</Text>
)}
</View>
)
}
You could alternatively use JavaScript strings declared before return along with this method.
Return in if Block
render() {
if(this.state.error) {
return (<Text>Long, detailed error message</Text>)
}
else {
return (<Text>No Error!</Text>)
}
}
The problem with this method is if that if you have a long render method and a small conditional change, you will have to nearly repeat the render function in each if block. I generally use this method as a last resort.

this is the simple one :
render()
{
return(
<View>
{this.state.error ?
(<View>
<Image source={{"error"}} />
<Text>An Error Happen</Text>
</View>)
:
(<View>
<List dataArray={this.state.items}></List>
</View>)
}
</View>
);
}
maybe can help you :)

You should try somthing like this:
export default class App extends Component {
render() {
if(this.state.error)
{
return (
<View>
<Image source={{"error"}} />
<Text>An Error Happen</Text>
</View>
)
}
else {
return (
<View>
<List dataArray={this.state.items}></List>
</View>
);
}
}
}

You can do this:
render()
{
return(
<View>
{this.state.error &&
<View>
<Image source={{"error"}} />
<Text>An Error Happen</Text>
</View>
}
{!this.state.error &&
<View>
<List dataArray={this.state.items}></List>
</View>
}
</View>
);
}

I suggest to take advantage of js in this case:
{ this.state.error &&
<View>
<Text>show error</Text>
</View>
}
{ !this.state.error &&
<View>
<Text>all good</Text>
</View>
}
It can look better than ternary in some cases.

Related

DoneButton is not rendering in 'react-native-app-intro-slider-rerender-on-prop-change'

I am trying to make a multiple choice test with a few questions using React Native package 'react-native-app-intro-slider'. The problem was that this package was not rerendering the items when something changes, state for example. I found a similar or refactored package called 'react-native-app-intro-slider-rerender-on-prop-change' that did the same thing but rerendered items on a state change. But the problem is that it does not render the Done button at last slide.
The last package i used was this :
import AppIntroSlider from 'react-native-app-intro-slider-rerender-on-prop-change';
The render method for the 'MCTContainer' (Multiple Choice Container) class is :
render() {
if (this.state.showRealApp) {
this.props.navigation.navigate('TopicGroupDetails', { topicGroup: this.state.topicGroup });
return null;
} else {
const questions = this.state.questions;
return (
<AppIntroSlider
renderItem={this._renderItem}
slides={questions}
onDone={this._onDone}
onSkip={this._onDone}
activeDotStyle={{ backgroundColor: '#039BE5' }}
showPrevButton
showNextButton
showSkipButton
showDoneButton
renderPrevButton={this._renderPrevButton}
renderNextButton={this._renderNextButton}
renderSkipButton={this._renderSkipButton}
renderDoneButton={this._renderDoneButton}
/>
)
}
}
and its renderDoneButton method is like following :
_renderDoneButton = () => {
return (
<View style={styles.buttonCircle}>
<Icon
name="check"
color="#039BE5"
size={24}
style={{ backgroundColor: 'transparent' }}
/>
</View>
);
};
This is actually the same, exactly the same as I used for the component 'SliderComponent' where I show tutorial introductory text in multiple slides. It renders the 'done' button fine. But the only differenence is that I used package 'react-native-app-intro-slider' there, not 'react-native-app-intro-slider-rerender-on-prop-change'.
Please help me if someone has encountered such a problem. Thanx in advance ...
I finally solved it.
I just added a condition on "renderItem" function of the "AppIntroSlider", that checks whether it is the last slide. If it is it renders a button that calls "AppIntroSlider"-s "_onDone" method that completes the slide show.
_renderItem = ({item}) => {
return(
{
(this.state.isLastSlide) ?
(
<TouchableHighlight
onPress={this._onDone}
>
<View>
<Text>
COMPLETE SLIDE SHOW
</Text>
<Icon
name="check"
color="white"
size={24}
/>
</View>
</TouchableHighlight>
) :
(<View></View>)
}
)
}

ReactiveSearch how to stop initial query on load

So I've got ReactiveSearch working fine but I've noticed on the initial load it performs a query to fetch items - given my index will have perhaps a million items in it I'd ideally like to turn this off and only return results from the autosuggest?
<ReactiveBase
app="tths-shop-items"
url="my-es-cluster"
credentials="user:password"
>
<ScrollView>
<View style={styles2.container}>
<DataSearch
componentId="searchbox"
dataField={[
'name'
]}
placeholder="Search"
/>
<ReactiveList
componentId="results"
dataField="name"
size={7}
showResultStats={true}
pagination={true}
react={{
and: "searchbox"
}}
onData={(res) => {
return (
<View style={styles2.result}>
<Image source={{ uri: res.image.replace('http', 'https') }} style={styles2.image} />
<View style={styles2.item}>
<Text style={styles2.title}>{res.name}</Text>
</View>
</View>
)}
}
/>
</View>
</ScrollView>
</ReactiveBase>
EDIT
I also tried adding the default value in order to try and stop the initial query returning data. But it doesn't seem to work as expected.
defaultValue="3245423 kjhkjhkj 2kj34h12jkh 213k4jh12"
EDIT 2:
I've also tried defaultQuery in the following format and added it to the reactiveList and dataSearch components this gives me an error which is undefined is not an object 'this.defaultQuery.sort' - if I add sort to both queries it makes no difference:
defaultQuery={() =>
{
query: {
match_none: {}
}
}
}
I know it's an old question, but I stumbled upon the same problem.
My solution looks a little bit different - with the onQueryChange prop.
onQueryChange={
function(prevQuery, nextQuery) {
if ('match_all' in nextQuery['query']) {
nextQuery['query'] = { match_none: {} }
}
}
}
This will disable the ResultList with all results showing and only show results after you've selected any filter or entered a search term.
So here's one answer, you store the value that you click via the searchbox in state and then fiddle with the defaultQuery from there. Note default query does match_none: {} if there's no search text.
It's a bit inefficient as you still do a query that returns nothing, but it works - I'll leave this question open to give any better answers time to come up.
<ScrollView>
<View style={styles.mainContainer}>
<DataSearch
componentId="searchbox"
dataField={[
'name'
]}
placeholder="Search"
queryFormat="and"
noInitialQuery={true}
onValueChange={(value) => {
if(value === ''){
this.setState({searchText: null})
}
}}
onValueSelected={(value, cause, source) => {
this.setState({searchText: value.value})
}
}
/>
<ReactiveList
componentId="results"
dataField="name"
size={7}
showResultStats={true}
pagination={true}
react={{
and: "searchbox"
}}
defaultQuery={()=> {
if(this.state.searchText !== null){
return {
query: {
match: {
name: this.state.searchText
}
}
}
} else {
return {
query: {
match_none: {}
}
}
}
}}
onData={(res) => {
return (
<View style={styles2.result}>
<Image source={{ uri: res.image.replace('http', 'https') }} style={styles2.image} />
<View style={styles2.item}>
<Text style={styles2.title}>{res.name}</Text>
</View>
</View>
)}
}
/>
</View>
</ScrollView>
The selected answer was very useful but I changed the defaultQuery to use the original query in the event a search term is present:
defaultQuery={()=> {
if(this.state.searchText !== null){
return {
}
} else {
return {
query: {
match_none: {}
}
}
}
}}

React Native - Function doesn't seem to be called

I have a simple app with 2 images. When I click on image1, I want to display hello on the console.
But my function doesn't write anything in the console.
I didn't use a function and called directly console.log in the 2nd image and it works.
Do you know what is wrong with my function?
(I also used makeALogHello.bind(this) but it doesn't change the behavior).
export default class App extends React.Component {
constructor(){
super();
}
makeALogHello(){
console.log("hello");
}
render() {
return (
<View>
<TouchableOpacity style ={{flex:1}}
onPress={() => {this.makeALogHello} }>
<Image style ={styles.container}
resizeMode="contain"
source={require("./images/image1.png")}/>
<Text>ImageNb1</Text>
</TouchableOpacity>
<TouchableOpacity style ={{flex:1}}
onPress={() => {console.log("hi")} }>
<Image style ={styles.container}
resizeMode="contain"
source={require("./images/image2.png")}/>
<Text>ImageNb2</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
You need to call the function in your arrow function:
onPress={() => {this.makeALogHello()} }
Or simply pass the reference to your function, without wrapping it:
onPress={this.makeALogHello}

undefined is not a function in TouchableOpacity onPress

The question is almost similar to this one :
touchableopacity onpress function undefined (is not a function) React Native
But the problem is, I am getting the error despite the fact that I have bind the function. Here is my TouchableOpacity component:
<TouchableOpacity style={styles.eachChannelViewStyle} onPress={() => this.setModalVisible(true)}>
{item.item.thumbnail ?
<Image style={styles.everyVideoChannelThumbnailStyle} source={{uri: item.item.thumbnail}} />
: <ActivityIndicator style= {styles.loadingButton} size="large" color="#0000ff" />}
<Text numberOfLines={2} style={styles.everyVideoChannelVideoNameStyle}>
{item.item.title}
</Text>
</TouchableOpacity>
And this is my setModalVisible function:
setModalVisible(visible) {
console.error(" I am in set modal section ")
this.setState({youtubeModalVisible: visible});
}
Also, I have bind the function in constructor as follows:
this.setModalVisible = this.setModalVisible.bind(this);
But, I am still getting same error that undefined is not a function. Any help regarding this error?
The render method and your custom method must be under the same scope. In code below I have demonstrated the same. I hope you will modify your code accordingly as I assume you got the gist :)
class Demo extends Component {
onButtonPress() {
console.log("click");
}
render() {
return (
<View>
<TouchableOpacity onPress={this.onButtonPress.bind(this)}>
<Text> Click Me </Text>
</TouchableOpacity >
<View>
);
}
}
Alternatively binding method in constructor will also work
class Demo extends Component {
constructor(props){
super(props);
this.onButtonPress= this.onButtonPress.bind(this);
}
onButtonPress() {
console.log("click");
}
render() {
return (
<View>
<TouchableOpacity onPress={this.onButtonPress()}>
<Text> Click Me </Text>
</TouchableOpacity >
<View>
);
}
}
I'm not sure if this will help but I write my functions this way and haven't encountered this problem.
If I were you I'd try binding the function in the place where you declare it.
setModalVisible = (visible) => {
this.setState({ youtubeModalVisible: visible });
}
If you do this, you don't have to bind in the constructor.
constructor(props) {
...
// Comment this out to see it will still bind.
// this.setModalVisible = this.setModalVisible.bind(this);
...
}
Lastly, if this function will only set the modal's state to visible, you might want to remove the argument and pass it this way.
<TouchableOpacity style={styles.eachChannelViewStyle} onPress={this.setModalVisible}>
...
</TouchableOpacity>
// Refactored function declaration would look like this
setModalVisible = () => {
this.setState({ youtubeModalVisible: true });
}

how to write if else under return react native

hope you are doing well.
I am stuck in little problem is i want to pass a tag only if my condition goes true.
for ex:
render(
return(
<View>
{
if(data==='test')
{
<Text>Hello this is Test Execution </Text>
}
}
</View>
)
)
i want to do exactly like above example.
i get some errors i can't understand what to do so please help me.
Thank you
A short and safe way would be to use a ternary operator and render null if false:
{ data === 'test' ? <Text>Hello this is Test Execution </Text> : null }
You need to write a function which optionally renders your text.
renderText(data) {
if (data === 'test') {
return <Text>Hello this is Test Execution </Text>;
}
}
render() {
return(
<View>
{this.renderText(data)}
</View>
);
}
You could try this:
render(
return(
<View>
{ (data==='test') && <Text>Hello this is Test Execution </Text>}
</View>
)
)
But I'd suggest the following syntax:
render(
if (data === 'test') {
return (
<View>
<Text>Hello this is Test Execution </Text>
<View>
)
}
return null;
)
You can do like this
return(){
<View>
{data === 'test' && <Text>Hello this is Test Execution </Text>}
</View>
}
You can try like
{(data === 'test') && <Text>Hello this is Test Execution</Text>}
Hope this will help.