my Button cannot change a state in another react native component - react-native

Why does the following code not work? In this test I simply try to show a state of the component Board, when the Button is clicked. But I get a TypeError: undefined is not an object.
var board = (<Board/>);
return (
<View>
{ board }
<Button
title="Press me"
onPress={() => Alert.alert(board.state.lastRefresh)}
/>
</View>
);
};
The Board component has this constructor:
constructor(props) {
super(props)
this.state = {
lastRefresh: Date(Date.now()).toString(),
}
...

If your Board component is something like this:
import PageTwo from 'PageTwo';
export default class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
lastRefresh: Date(Date.now()).toString(),
}
}
render() {
return (
<View>
<PageTwo lastRefresh={this.state.lastRefresh}>
</PageTwo>
</View>
)
}
}
You can access your props by this way from PageTwo component:
export default class PageTwo extends React.Component {
render() {
return (
<View>
<Button
title="Press me"
onPress={() => Alert.alert(this.props.lastRefresh)}
/>
</View>
)
}
}

Related

Is it possible to setState on other function tag?

Here is my code,
This code is working fine use "setState" to set new variable in componentDidMount tag.
export default class App extends React.Component {
constructor(props){
super(props);
this.state = {
name: "peter",
}
}
componentDidMount(){
this.setState({name:"sam"});
}
render(){
return (
<View>
<Text>
{this.state.name}
</Text>
</View>
)
}
}
But I want to create a new function to set it.
export default class App extends React.Component {
constructor(props){
super(props);
this.state = {
name: "peter",
}
}
changename(){
this.setState({name:"sam"});
}
render(){
this.changename();
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
{this.state.name}
</Text>
</View>
)
}
}
It displays
Minified React error #185;
Error
componentDidMount is work,
but it is not working on my own function tag
any idea how to fix it
Thank you very much.
You have put an unconditional state change in render. Because of that your render triggers a state change which triggers a re-render which again triggers a state change - An infinite loop.
You could put some sort of condition on which to trigger a state change for example:
export default class App extends React.Component {
constructor(props){
super(props);
this.state = {name: "peter"}
}
changename(){ this.setState({name:"sam"}); }
render(){
if(this.state.name==='peter')
this.changename();
return (
<View>
<Text>{this.state.name}</Text>
</View>
)
}
}

How change a state variable via props?

I'm trying do show a modal screen with a button, when i press the button the modal will appears. The variable that is responsable for it is modalVisible and its a variable state. But if my button is not in the same class of my screen Profile i'm not able to change the variable, at last i dont know a way to do:
class Carrousel extends React.Component {
render () {
return (
<Button
title= 'press me to show up'
onPress= {() => this.props.visible = true}
/>
);
}
}
export default class Profile extends React.Component {
constructor(props) {
super(props);
this.state = {
modalVisible: true,
};
}
render() {
return (
<View>
<Modal
visible = {this.state.modalVisible}>
</Modal>
<Carrousel visible = {this.state.modalVisible}/>
</View>
);
}
}
Is there an way to change this variable modalVisible in another class? Or is there another way to i show the modal with a button in another class?
*The carrousel class is another file Carrousel.js.
You have to set a function as a prop that changes the state on the Parent Component. I haven't tried but it should be something like this:
class Carrousel extends React.Component {
render () {
return (
<Button
title= 'press me to show up'
onPress= {() => this.props.setVisible()}
/>
);
}
}
export default class Profile extends React.Component {
constructor(props) {
super(props);
this.state = {
modalVisible: false,
};
this.setVisible = this.setVisible.bind(this);
}
setVisible() {
this.setState({
modalVisible: true,
})
}
render() {
return (
<View>
<Modal
visible = {this.state.modalVisible}>
</Modal>
<Carrousel setVisible={this.setVisible}/>
</View>
);
}
}

Passing state to child component

In the following React Native scenario, how can I pass the variable userId from the 'parent' component to the 'child' component?
I have a 'parent' component like so:
export class UserProfileScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
userId: 123,
}
}
render() {
return(
<View>
<UserIntro />
</View>
)
}
}
And a 'child' component like so:
export class UserIntro extends React.Component {
render() {
return(
<View>
<Text>Introduction for user {userId}</Text>
</View>
)
}
}
export class UserProfileScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
userId: 123,
}
}
render() {
return(
<View>
<UserIntro id={this.state.userId} />
</View>
)
}
}
export class UserIntro extends React.Component {
render() {
return(
<View>
<Text>Introduction for user {this.props.id}</Text>
</View>
)
}
}
You can pass anything(JSON object,JSON Array,simple arrays,float and even function etc) from parent to child using props. There is no limit of props number.
you can execute parent function from child as well using props
export class UserProfileScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
userId: 123
};
}
getUpdatedUserID = updatedId => {
this.setState({userId:updatedId});
alert(updatedId);
};
render() {
return (
<View>
<UserIntro id={this.state.userId} getUpdatedUserID={this.getUpdatedUserID} />
</View>
);
}
}
export class UserIntro extends React.Component {
updateUserId=()=>
{
this.props.getUpdatedUserID((int)(this.props.id)+1);
}
render() {
return (
<View>
<Text>Introduction for user {this.props.id}</Text>
<Button onPress={this.updateUserId} />
</View>
);
}
}

How to use onPress on a custom component?

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

loading/importing contents of Modal from another js (class) file in react-native

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