How change a state variable via props? - react-native

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

Related

my Button cannot change a state in another react native component

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

passing array state to another class react native

I am new to React Native. I am making a lunch picker app for practice, and I wonder how to pass array of state to another class.
What I want to do is: show all data of array in child screen, so users can check the data by clicking on a button.
However, it seems like my code returns null array instead of getting original array. All codes are in one file, App.js
Home screen
class HomeScreen extends React.Component {
//initial
constructor(props) {
super(props);
this.state = {
isReady: false,
myMenu: '????',
menutext: '',
randomArray: ['a', 'b', 'c'],
};
}
render() {
return (
<View style={[styles.mainContainer]}>
<DetailsScreen menuListAA={this.state.randomArray} />
<Button
label="Show all menu"
onPress={() => {
/* 1. Navigate to the menu page route with params */
this.props.navigation.navigate('Details', {
itemId: 0,
otherParam: 'Show all menu',
});
}}
/>
</View>
Details screen
class DetailsScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
static navigationOptions = {
title: 'All menu',
};
loadMenuList() {
const allMenuList = this.props.menuListAA;
return allMenuList.map((item, index) => <Text key={index}>{item}</Text>);
}
render() {
return (
<ScrollView>
<View style={styles.row}>{this.props.menuListAA}</View>
<Button
label="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</ScrollView>
);
}
}
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailsScreen,
},
{
initialRouteName: 'Home',
}
);
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
Let me know if you need more information.
Please replace your code with one below :
Home screen
class HomeScreen extends React.Component {
//initial
constructor(props) {
super(props);
this.state = {
isReady: false,
myMenu: '????',
menutext: '',
randomArray: ['a', 'b', 'c'],
};
}
render() {
return (
<View style={[styles.mainContainer]}>
<DetailsScreen menuListAA={this.state.randomArray} />
<Button
label="Show all menu"
onPress={() => {
/* 1. Navigate to the menu page route with params */
this.props.navigation.navigate('Details', {
itemId: 0,
otherParam: 'Show all menu',
});
}}
/>
</View>
Doubts Detail : replace View with Text component
class DetailsScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
}
}
static navigationOptions = {
title: 'All menu',
};
loadMenuList() {
const allMenuList = this.props.menuListAA;
return allMenuList.map((item, index) => <Text key={index}>{item}</Text>);
}
render() {
return (
<ScrollView>
//change View with Text as view cannot render characters and error says the same
<Text style={styles.row}>{this.props.menuListAA}</Text>
<Button
label="Go back"
onPress={() => this.props.navigation.goBack()}
/>
</ScrollView>
);
}
}
const RootStack = createStackNavigator(
{
Home: HomeScreen,
Details: DetailsScreen,
},
{
initialRouteName: 'Home',
}
);
const AppContainer = createAppContainer(RootStack);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
you can pass data from parent to child by set props for child component like this: <Child data={this.state.yourData} /> //the props name is data,
then in child component in componentWillMount() you can access it:
ComponentWillMount(){
this.setState({childData: this.props.data}) // childData is an state of child component,rename it to your own`
}
in some case data maybe changed so we must to check this in componentDidUpdate() :
componentDidUpdate(){
if(this.props.data != this.state.childData){ //it is necessary because this function called many time's
this.setState({childData: this.props.data})
}
if you was in parent & want to give any data from child you must pass a function that returned data as like below:
<Child getData={(value)=> console.log(value)} />
then in your child you can do this:
this.props.getData(anyDataYouWantGetInParent)
hope this answer will be helpful,let me know any question
good luck.

How would I disable a function by clicking on TextInput

I have this class for blinking text:
class BlinkerFluid extends React.Component {
constructor(props) {
super(props);
this.state = {
isShowingText: true,
TextInputName = ''
};
setInterval(() => {
this.setState(previousState => {
return { isShowingText: !previousState.isShowingText };
});
}, 700);
}
render () {
let display = this.state.isShowingText ? this.props.text : ' ';
return (
<Text style={styles.other}>{display}</Text>
);
}
}
And this class to render the blinking text:
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = { text: 'x' };
}
render() {
return (
<View style={styles.container}>
<Text style={styles.other}>$ root | > </Text>
<BlinkerFluid text=' _' />
<TextInput style={styles.lol}
onChangeText={(text) => this.setState({text})}
value={this.state.text}
/>
</View>
);
}
}
I want to be able to stop the blinking of the text when I click on the TextInput prop and/or write to it.
How would I go about doing that?
I've been trying to search for an answer on my own, read the docs, but nothing has helped.
Any help is appreciated!
You could try something like the below code snippet (I've only included the code for App. You can implement the paused functionality in the BlinkerFluid however you want.
Basically, I'm storing in the state whether the blinker should be paused or not, then passing that value through to the BlinkerFluid component as a prop. You can set the pauseBlinker state easily, perhaps on onChangeText as in the example, or on press of a TouchableOpacity element etc.
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
text: 'x',
pauseBlinker: false,
};
}
render() {
return (
<View style={styles.container}>
<Text style={styles.other}>$ root | > </Text>
<BlinkerFluid text=' _' paused={this.state.pauseBlinker} />
<TextInput style={styles.lol}
onChangeText={(text) => this.setState({ text, pauseBlinker: true, })}
value={this.state.text}
/>
</View>
);
}
}

render is not calling on state change

export default class TopMiddleLoadingView extends React.Component{
size = 66;
constructor(props) {
super(props);
this.state = {
fill : 99,
timeLeft : props.timeLeft
}
}
onPress(){
this.setState = {
...this.state, fill:10
}
}
componentWillUpdate(nextProps, nextState) {
alert("componentWillUpdate");
}
render(){
alert("render")
return(
<View style={{width:this.size, height:this.size}}>
<View style={[styles.absoluteCenter,{zIndex:999}]}>
<Thumbnail source={Images.seaImg}></Thumbnail>
</View>
<Text>{this.state.fill}</Text>
<Button
style={{width:50,height:50,backgroundColor:"red",position:"absolute",zIndex:999}}
onPress={this.onPress}
></Button>
</View>
);
}
}
on button press, onPress function is clicked, and change the state of the component, but the render function is not calling.
I am very new to react native. Any idea?
You aren't changing the state either let alone re render. And if you want to re render then you should change state using setState() method. Also, you need to refresh you javascript this knowledge
export default class TopMiddleLoadingView extends React.Component{
size = 66;
constructor(props) {
super(props);
this.state = {
fill : 99,
timeLeft : props.timeLeft
}
}
onPress = () => {
this.setState({fill:10})
}
componentWillUpdate(nextProps, nextState) {
alert("componentWillUpdate");
}
render(){
alert("render")
return(
<View style={{width:this.size, height:this.size}}>
<View style={[styles.absoluteCenter,{zIndex:999}]}>
<Thumbnail source={Images.seaImg}></Thumbnail>
</View>
<Text>{this.state.fill}</Text>
<Button
style={{width:50,height:50,backgroundColor:"red",position:"absolute",zIndex:999}}
onPress={this.onPress}
></Button>
</View>
);
}
}
Render method is called whenever there is change in state of that component. You should use this.setState({...this.state, fill:10} for updating state of the component. This must cause render function to fire again, if there is not any other logic written inside shouldComponentUpdate() for conditional rendering.
Hope this helps. Also check out,
What the difference of this.state and this.setstate in ReactJS?

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