I'm quite new to react-native. Here Card is a view component having nothing special but text view with dimensions as flex: 1 I've my App.js as:
export default class App extends React.Component {
constructor(props: props){
super(props);
this.state = {
};
}
render() {
return (
<View style={styles.container}>
<ViewPager style={styles.pager} children={Card,Card,Card} count={3} height={100} width={100} selectedIndex={0} initialPage={0}>
</ViewPager>
</View>
);
}
}
I'm using the F8 app ViewPager which is made for both ViewPager & ScrollView for Android & iOS respectively. Which is as here (not inserting code here to keep it clean): ViewPager Component In F8 App
So what I need to know is how to pass a children to the ViewPager from my App.js
I'm not sure this is what you're looking for or what? Hope it will help you for some idea.
App.js passing value as View and Text
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<ViewPager style={styles.pager}>
// Children Array or any View as you prefer //
<Card>
<View>
<Text>Hello</Text>
</View>
</Card>
/////// End Block /////
</ViewPager>
</View>
);
}
}
ViewPager.js get value as props from App.js
export default class ViewPager extends React.Component {
render(){
return(
<View>
// these all props that pass from APP component
{this.props.children}
</View>
);
}
}
Related
I am mapping array to component.
{this.state.forms.map((data)=><Box data={data} />)}
and the code for component Box is
import React,{Component} from 'react'
import {View,Text,ScrollView,Image,Button,StyleSheet,AsyncStorage} from 'react-native'
class Login extends Component{
constructor(props){
super(props)
this.state = {
forms:[],
}
this.onSetCompany = this.onSetCompany.bind(this)
}
onSetCompany(data){
console.log(data)
// AsyncStorage.setItem('Company',data);
this.props.navigation.navigate('CompanyDeatails')
}
render(){
return(
<View style={style.container}>
{console.log(this.props.data)}
<View style={style.box}>
<View style={style.box1}>
<Text style={style.row2}>{this.props.data.CompanyName} bkb</Text>
</View>
<View style={style.box3}>
<Text style={style.row2}>{this.props.data.LastDate} </Text>
</View>
</View>
<View style={style.buttonBox}>
<View style={style.button}>
<Button color="#6d5d17" title="Fill" onPress={()=>this.props.navigation.navigate('CompanyDeatails')}></Button>
</View>
</View>
</View>
)
}
}
export default Login
var style = StyleSheet.create({
.....
})
and my Routes
export default class App extends Component{
render(){
return(
<Links />
)
}
}
const Links = DrawerNavigator({.....,
CompanyDeatails:{screen:CompanyDeatails},
....,
},{contentComponent:props => <Slider {...props}/>
})
When i Map array to Box then navigation in that box is not working.I have working navigation to which are working on my rest of app but not in this particular component.
Like
in login.js, I have this.props.navigation.navigate('C1')
Which is working but when I paste same line in Box component it throw error.
Can not read property navigate of undefined
If Box component is not part of navigator then, you should wrap it within withNavigation function inorder to access the navigation object. Take a look at the doc here
Consider the following example
import React from 'react';
import { withNavigation } from 'react-navigation';
class Box extends React.Component {
...
render() {
...
}
}
export default withNavigation(Box);
Now, within the Box component, you can access this.props.navigation.navigate function.
Hope this will help!
So, I've just figured out today that only changing state in a React Native app triggers a re-render of the component. I'm changing state, but I'm doing it from a child component, and it seems to getting stuck in some loop, and () => { this.setState({current_time:'whatever'}) doesn't seem to do anything at all. How can I change my App.js's current_time in state from TimePicker.js?
App.js
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
current_time:'initial time, unchanged in state',
};
}
render() {
let s = styles;
return (
<View style={s.contain}>
<TimePicker />
<ShowTime current_time={this.state.current_time} />
</View>
);
}
}
TimePicker.js
class TimePicker extends Component {
constructor(props){
super(props);
}
render(){
let s = styles;
return(
<TouchableOpacity>
<View style={s.contain} onPress={
/*
set this.state.current_time in parent to the actual current time
this.setState({current_time:'changed'}) seems to cause an infinite loop?
() => { this.setState({current_time:'changed'}) } doesn't seem to do anything
*/
}>
<Text>I will change the time in state.</Text>
</View>
</TouchableOpacity>
)
}
};
ShowTime.js
class ShowTime extends Component {
constructor(props){
super(props);
}
render(){
let s = styles;
return(
<View style={s.contain}>
<Text>{this.props.current_time}</Text>
</View>
)
}
};
Create a function in App.js and pass it as prop to TimePicker Component and the purpose of this function should be to setState . e.g
App.js
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
current_time:'initial time, unchanged in state',
};
}
currentTimeHandler = (newCurrentTime) => {
this.setState({current_time: newCurrentTime});
}
render() {
let s = styles;
return (
<View style={s.contain}>
<TimePicker getTime={ this.currentTimeHandler }/>
<ShowTime current_time={this.state.current_time} />
</View>
);
}
}
TimePicker.js
class TimePicker extends Component {
constructor(props){
super(props);
}
render(){
let s = styles;
return(
<TouchableOpacity onPress={() => this.props.getTime('changes will be passed here')}>
<View style={s.contain} >
<Text>I will change the time in state.</Text>
</View>
</TouchableOpacity>
)
}
};
The reason is the setState only set the existing states locally in the js file. that would be your Timepicker.
In your case TimePicker is a child(or sub branch) of App (Your app stores your state, by your current build, and will never be changed by a child). You will need create two functions one in TimePicker and another App. TimePicker will handle the data and send it, via prop, the App will receive the prop and then trigger another function to setState.
Pass data from child to parent in React
This is the best one i can find.
Best read this as well:
https://reactjs.org/docs/react-component.html
It does say, setState only affect to local states, your state you want to set is not local.
Let's assume I have this custom component:
export default class Button extends Component {
render(){
return(
<TouchOpacity>
<Text> Button </Text>
</TouchOpacity>
)
}
}
And I use it in a parent component like this :
export default class MainPage extends Component {
render(){
return(
<Button onPress={ this.doSomething }></Button>
)
}
}
For some reason (unknown to me at least) this onPress even won't happen.
I'm pretty new to react-native btw. I believe I must find a way to enable this kind of event handling.
Is it possible to get a small example how to achieve that based on my examples above ?
So, just found out how to handle this.
export default class Button extends Component {
constructor(props){
super(props)
}
render(){
return(
<TouchableOpacity
onPress={this.props.onPress}
>
<Text> Button </Text>
</TouchableOpacity>
)
}
}
and
export default class MainPage extends Component {
render(){
return(
<Button onPress={ this.doSomething }></Button>
)
}
}
Long story short: since the onPress I'm passing is a prop in the MainPage, I'm passing it a function (this.doSomething) which later on is activated in Button's onPress.
Nick's answer is right.Along with that if you want to call separate function for both child and parent component then you can use onPressOut. This will help to manage state of componant
export default class Button extends Component {
constructor(props){
super(props)
}
onClickListen = () => {
if (this.state.isSelected === false) {
this.setState({isSelected:true});
isSelectedPass=true;
}
else {
this.setState({isSelected:false});
isSelectedPass=false;
}
}
render(){
return(
<TouchableOpacity
onPress={this.props.onPress} onPressOut={this.onClickListen}
>
<Text> Button </Text>
</TouchableOpacity>
)
}
}
export default class MainPage extends Component {
render(){
return(
<Button onPress={ ()=>this.doSomething }></Button>
)
}
}
My modal displays an input form. I want to import contents of my Modal from another js file for keeping the main code shorter. I am actually able to import contents of my Modal from another class file by calling component's class name as jsx tag, but in this case I cannot pass state variables of main component to inner component of the modal or vice versa. And, I don't know if it is possible to receive data from the modal in this case. I know that I could use navigator with passProps, but I want to use just a modal for this purpose. For instance:
this is main Component:
class Main extends React.Component {
constructor(props){
super(props);
this._showAddNewModal = this._showAddNewModal.bind(this);
this.state = {
addNewShow: false,
mytext: '' // this should be updated through Modal.
}
}
render(){
return (
<TouchableHighlight onPress={() => {this._showAddNewModal();}}>
<Text> Show my modal </Text>
</TouchableHighlight>
<Modal visible={this.state.addNewShow}>
<MyModalContents />
</Modal>
);
}
_showAddNewModal(){
this.setState({addNewShow: true});
}
}
this is the component to be displayed in the modal:
class MyModalContents extends React.Component { // extends Modal?
constructor(props){
super(props);
this.state = {mytext: ''}
}
render(){
<View>
<TextInput onChangeText={(text) => this.setState({mytext: text})} />
</View>
}
}
I can't even close the modal because the state of 'addNewShow' is not accessible from MyModalContents. Any help will be appreciated.
You can pass props to a child component by cloning it with React.cloneElement. Here's an example of how you could use it with your modal:
class Main extends React.Component {
constructor(props){
super(props);
this.state = {
mytext: '' // this should be updated through Modal.
}
}
_showAddNewModal(){
this.refs.modal.show();
}
render(){
return <View>
<TouchableHighlight onPress={this._showAddNewModal}>
<Text> Show my modal </Text>
</TouchableHighlight>
<Modal parent={this} ref="modal">
<MyModalContents />
</Modal>
</View>
}
}
Modal
class Modal extends React.Component {
constructor(props){
super(props);
this.state = {
visible: false,
}
}
show() {
this.setState({visible: true});
}
close(){
this.setState({visible: false});
}
render(){
return <View style={{opacity: this.state.visible ? 1 : 0}} pointerEvents={this.state.visible ? 'auto' : 'none'}>
{/* can pass props with second argument */}
{React.cloneElement(this.props.children, {
parent: this.props.parent,
modal: this
})}
</View>
}
}
MyModalContents
class MyModalContents extends React.Component {
constructor(props){
super(props);
}
_updateModalState() {
const self = this;
// will update the "Main" component state as props are passed through modal
this.props.parent.setState({myText: 'Updated Text!'}, () => {
self.props.modal.close();
});
}
render(){
return <View>
<TouchableHighlight onPress={this._updateModalState}>
<Text> Update Modal State </Text>
</TouchableHighlight>
</View>
}
}
component A
render(){
<View>
{this.renderB()}
{this.renderC()}
</View>
}
component B
super(props){
this.state={text: (this.props.text) ? this.props.text : '' }
}
render(){
}
component C
super(props){
}
render(){
<View>
<TouchableHighlight onPress={
...here I want to modify text state of component B
}></TouchableHighlight>
</View>
}
Is it possible to modify state of sibling like so? or should I move text properties here to component A?
When you need to share state between components, move that state up to their common parent and push them down through props.
Here's the gist of what I'm getting at. Obviously, you'd need to pass up actual values.
class ComponentA extends React.Component{
constructor(props){
super(props);
this.state = {
text: '',
}
}
render(){
return (
<View>
<ComponentB text={this.state.text}>
<ComponentC onPress={(value) => this.setState({text: value})}>
</View>
)
}
}
class ComponentB extends React.Component{
render(){
return(
<Text>{this.props.text}</Text>
)
}
}
class ComponentC extends React.Component{
render(){
return(
<View>
<TouchableHighlight onPress={this.props.onPress} />
</View>
)
}
}