React Native Iterate through Object After Button Click - javascript

I want to make it so that I can click a button and go to the next object in my json file. But I am unsure how to continue the for loop on click. I tried adding an i++ to the onpress event in the button but that doesnt work and just errors as I think on press needs to be a function. Any help would be fantastic! I am very new to react-native so sorry if this isnt the way to do it
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
Button
} from 'react-native';
var jsonData = require('./skull.json');
export default class flashcards extends Component {
render() {
var i = 0;
for (i; i < 50; i++) {
var skull = jsonData[i];
return (
<View style={styles.container}>
<Text>
Question #{jsonData.quiz.question[i].number}
</Text>
<Text>
{jsonData.quiz.question[i].question}
</Text>
<Image
source={{ uri: jsonData.quiz.question[i].picture }}
style={styles.thumbnail}
/>
<Button
title="Next Question"
color="#841584"
accessibilityLabel="Learn more about this purple button"
/>
</View>
);
}
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF'
},
thumbnail: {
width: 300,
height: 350
}
});
AppRegistry.registerComponent('flashcards', () => flashcards);

Ya I think you need to create state to increase your i , and set the state on your onPress event like this :
export default class flashcards extends Component {
constructor(props) {
super(props);
this.state = {i: 0};
}
onButtonPress = () => {
if(this.state.i < 50){
this.setState({
i: this.state.i + 1
});
}
}
render() {
return (
<View style={styles.container}>
....//your code
<Button
onPress={this.onButtonPress}
title="Next Question"
color="#841584"
accessibilityLabel="Learn more about this purple button"
/>
</View>
);
}
}
And to call json data you have to change i with this.state.i like this :
jsonData.quiz.question[this.state.i].question
For more details you have to understand about state on react native, you can read on the documentation. I hope this answer can help you.

You need to do like this because this.setState will cause 50 times to re-render when You do this.setState in loop.
export default class flashcards extends Component {
constructor(props) {
super(props);
this.state = {i: 0};
}
onButtonPress = () => {
let val = this.state.i;
if(val < 50){
va += 1
}
this.setState({ i: val });
}
render() {
return (
<View style={styles.container}>
....//your code
<Button
onPress={this.onButtonPress}
title="Next Question"
color="#841584"
accessibilityLabel="Learn more about this purple button"
/>
</View>
);
}
}

Related

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 })}

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

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

How to expand search bar after presses on search icon

I am somehow create an Search icon by a component and I just wanna know how to expand search bar icon when someone presses on it..
import { TouchableOpacity,View, Image} from 'react-native';
import { SearchBar } from 'react-native-elements';
export default class Search extends Component{
onClick(){
return <SearchBar/> // [![Seach Image][1]][1]not working
}
render(){
// not worrking
let search = <SearchBar/>;
return(
<View>
<TouchableOpacity
onPress={() => {
return search
}}
>
<Image
source={require('../images/tabs/search.png')}
style={{height: 40, width: 60}}
resizeMode={'contain'}
/>
</TouchableOpacity>
</View>
)
}
}
You should add a state to your component to control the behaviour of the header
import { TouchableOpacity, View, Image } from 'react-native';
import { SearchBar } from 'react-native-elements';
export default class Search extends Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
this.state = {
showSearchBar: false, // control what ever to render the searchbar or just the icon
};
}
onClick() {
let { showSearchBar } = this.state;
this.setState({
showSearchBar: !showSearchBar,
});
}
render() {
const { showSearchBar } = this.state;
return (
<View>
{!showSearchBar ? (
<TouchableOpacity onPress={this.onClick}>
<Image
source={require('../images/tabs/search.png')}
style={{ height: 40, width: 60 }}
resizeMode={'contain'}
/>
</TouchableOpacity>
) : (
<SearchBar />
)}
</View>
);
}
}

Custom Tabs using react-native

I have created custom tabs in react-native but I am unable to select a tab. I have initialized the state for the selected tab but do not know where to set the state.
here is my code:
'use strict';
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
Image,
View
} from 'react-native';
var Dimensions = require('Dimensions');
var windowSize = Dimensions.get('window');
var bg = require('image!bg');
class TabView extends Component {
constructor(props) {
super(props);
this.state = {
selectedTab: 'list',
selectedTab: 'map'
};
}
render() {
return (
<View style={styles.container}>
<Image style={styles.bg} source={bg} />
<View style={styles.tabView}>
<View style={[styles.listView,styles.selectedView]}>
<Text>List View</Text>
</View>
<View style={[styles.listView,{}]}>
<Text>Map View</Text>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
bg: {
position: 'absolute',
left: 0,
top: 0,
width: windowSize.width,
height: windowSize.height
},
tabView: {
flexDirection: 'row',
//bottom: 200,
borderWidth:2,
borderColor:'rgba(4, 193, 3,1)',
borderRadius: 5,
marginHorizontal: 20,
marginTop: 50
},
listView: {
flex: 2,
padding:7,
alignItems:'center'
},
mapView: {
flex: 2,
padding:7,
alignItems:'center'
},
selectedView: {
backgroundColor:'rgba(4, 193, 3,1)',
color: 'white'
}
});
module.exports = TabView
I just want to know where shall I add a check so that I can make a difference in the selected tab
Any help will be appreciated.
Please, check out the code here, to get an idea how it can be done
const Tab = (props) => {
let style = props.isSelected && styles.selectedTab || styles.normalTab;
return (
<View style={style}>
<TouchableHighlight onPress={() => props.onTabPress(props.id)}>
<Text>{props.title}</Text>
</TouchableHighlight>
</View>
)
}
class TabsView extends Component {
constructor(props) {
super(props)
this.state = {
selectedTab: 'one'
}
}
render() {
return (
<View>
<Tab onTabPress={this.onSelectTab.bind(this)} title="One" id="one" isSelected={this.state.selectedTab == "one"}/>
<Tab onTabPress={this.onSelectTab.bind(this)} title="Two" id="two" isSelected={this.state.selectedTab == "two"}/>
</View>
)
}
onSelectTab(selectedTab) {
this.setState({ selectedTab })
}
}
The above code splits your component in two parts, a logical part (TabsView) and a dumb presentational part (Tab)
The logical handles the clickHandler (onSelectTab) which is passed as a prop (onTabPress) to the dumb (Tab) Component.
I just want to know where shall I add a check so that I can make a difference in the selected tab
In the render method, it should go
example:
render() {
let FirstTabStyles = Object.assign(
defaultTabStyles,
(isFirstSelected && selectedStyles || {})
)
let SecondTabStyle = Object.assign(
defaultTabStyles,
(isSecondSelected && selectedStyles || {})
)
return (
<View>
<FirstTab style={FirstTabStyle} />
<SecondTab style={SecondTabStyle} />
</View>
)
}

Programmatically add a component in React Native

Suppose I have a simple React Native app like so:
'use strict';
var React = require('react-native');
var {
AppRegistry,
Text,
TouchableHighlight,
View,
} = React;
var ReactProject = React.createClass({
_onPressOut: function() {
// What do we do here?
},
render() {
return (
<View>
<Text>This text should be before</Text>
<Text>This text should be after</Text>
<TouchableHighlight onPressOut={this._onPressOut}>
<Text>Tap Me</Text>
</TouchableHighlight>
</View>
);
}
});
AppRegistry.registerComponent('ReactProject', () => ReactProject);
How can I dynamically insert a component between the first and second Text tags when the TouchableHighlight is pressed?
Try creating an array and attaching it to the state. You can then push items to the array, and reset the state.
https://rnplay.org/apps/ymjNxQ
'use strict';
var React = require('react-native');
var {
AppRegistry,
StyleSheet,
Text,
View,
TouchableHighlight
} = React;
var index = 0
var SampleApp = React.createClass({
getInitialState(){
return { myArr: [] }
},
_onPressOut() {
let temp = index ++
this.state.myArr.push(temp)
this.setState({
myArr: this.state.myArr
})
},
render() {
let Arr = this.state.myArr.map((a, i) => {
return <View key={i} style={{ height:40, borderBottomWidth:2, borderBottomColor: '#ededed' }}><Text>{ a }</Text></View>
})
return (
<View style={styles.container}>
<Text>First</Text>
{ Arr }
<Text>Second</Text>
<TouchableHighlight style={ styles.button } onPress={ () => this._onPressOut() }>
<Text>Push</Text>
</TouchableHighlight>
</View>
);
}
});
var styles = StyleSheet.create({
container: {
flex: 1,
marginTop:60
},
button: {
height:60,
backgroundColor: '#ededed',
marginTop:10,
justifyContent: 'center',
alignItems: 'center'
}
});
AppRegistry.registerComponent('SampleApp', () => SampleApp);
I've set up a working example here.
In react or react native the way component hide/show or add/remove does not work like in android or iOS. Most of us think there would be the similar stratedgy like
View.hide = true or parentView.addSubView(childView
But the way react native work is completely different. The only way to acheive this kind of functionality is to include your component in your DOM or remove from DOM.
Here in this example I am going set the visibility of text view based on the button click.
enter image description here
The idea behind this task is the create a state variable called state having the initial value set to false when the button click event happens then it value toggles. Now we will use this state variable during the creation of component.
import renderIf from './renderIf'
class fetchsample extends Component {
constructor(){
super();
this.state ={
status:false
}
}
toggleStatus(){
this.setState({
status:!this.state.status
});
console.log('toggle button handler: '+ this.state.status);
}
render() {
return (
<View style={styles.container}>
{renderIf(this.state.status)(
<Text style={styles.welcome}>
I am dynamic text View
</Text>
)}
<TouchableHighlight onPress={()=>this.toggleStatus()}>
<Text> touchme </Text>
</TouchableHighlight>
</View>
);
}
}
the only one thing to notice in this snippet is renderIf which is actually a function which will return the component passed to it based on the boolean value passed to it.
renderIf(predicate)(element).
renderif.js
'use strict';
const isFunction = input => typeof input === 'function';
export default predicate => elemOrThunk =>
predicate ? (isFunction(elemOrThunk) ? elemOrThunk() : elemOrThunk) : null;
With React components you don't want to think of actions reaching into the DOM and inserting components - you want to think components responding to actions. Theoretically, this component is already composed and ready, it just needs to know if it should be rendered or not:
var ReactProject = React.createClass({
getInitialState() {
// our *state* dictates what the component renders
return {
show: false
};
}
_onPressOut: function() {
// update our state to indicate our "maybe" element show be shown
this.setState({show: !this.state.show});
},
maybeRenderElement() {
if (this.state.show) {
// depending on our state, our conditional component may be part of the tree
return (
<Text>Yay!</Text>
);
}
return null;
}
render() {
return (
<View>
<Text>This text should be before</Text>
{this.maybeRenderElement()}
<Text>This text should be after</Text>
<TouchableHighlight onPressOut={this._onPressOut}>
<Text>Tap Me</Text>
</TouchableHighlight>
</View>
);
}
});
I've also made a helper that makes it easy to conditionally render things, render-if
renderIf(this.state.show)(
<Text>Yay</Text>
)
ECMA6 Syntax
import React, { Component } from 'react';
import {
View,
Text,
StyleSheet,
TextInput,
TouchableOpacity,
TouchableHighlight
} from 'react-native';
export default class fourD extends Component {
constructor(props) {
super(props);
let ele1 = (
<View key={1}>
<Text>Element {1}</Text>
<TouchableOpacity onPress={ () => this._add() }>
<Text>Add</Text>
</TouchableOpacity>
</View>
);
this.state = {
ele: [],
key: 1
}
this.state.ele.push(ele1);
}
_add(){
let key = this.state.key + 1;
let ele2 = (
<View key={key}>
<Text>Element {key}</Text>
<TouchableOpacity onPress={ () => this._add() }>
<Text>Add</Text>
</TouchableOpacity>
</View>
);
let ele = this.state.ele;
ele.push(ele2);
this.setState({ ele: ele,key : key})
}
render() {
return (
<View style={styles.container}>
<Text>This text should be before</Text>
{ this.state.ele }
<Text>This text should be after</Text>
<TouchableHighlight onPressOut={ () => this._add() }>
<Text>Tap Me</Text>
</TouchableHighlight>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "white",
}
})

Categories