I want to change client = {state:0}
You can access it by using this.client.state
I also have a child which contains a button.
I'm trying to change this 'state' variable when you press the button.
For some reason everything I find everything on the internet not working for me.
I've been stuck at it for 5 hours and I think it's time to ask help myself
import React from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity } from 'react-native';
import Home from './Components/Home';
import Activity from './Components/Activity';
export default class App extends React.Component {
client = {state:0}
render() {
if(this.client.state == 0){
return(
<View style={{flex: 1}}>
<Home />
<Child />
</View>
);
} else {
return(
<View style={{flex: 1}}>
<Activity />
<Child />
</View>
);
}
There are different ways of doing this. It could be done with Redux for example, but let's take a simpler approach.
Also note that it can't be done by props, because a child component cannot update its parents' props.
Also note that the way you are using the state seems rather strange. It should be set on the class level (or component level).
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {myProperty: 0};
}
}
You could pass a callback method to the Child React Component.
<Child callback={this.onButtonClick} />
On the Client Component, create that callback method:
onButtonClick() {
this.setState({buttonClicked: true});
}
To keep it clean, define the initial value in the constructor. You'll also have to bind the function to have a correct this parameter, otherwise the this variable will be from the event instead of the class you're expecting.
constructor(props) {
super(props);
this.state = {buttonClicked: false};
this.onButtonClick = this.onButtonClick.bind(this);
}
That's it for the Client component.
Now on the Child Component, you'll need to trigger this callback method when possible.
Imagine the Child has the following button, add an event handler on the child component as well, onChildButtonClick. You'll also have to bind in the constructor.
constructor(props) {
super(props);
// bind this for access to this class' data
this.onChildButtonClick = this.onChildButtonClick.bind(this);
}
onChildButtonClick() {
// Might want to do a typeof is function check here too
if (this.props.callback) {
// Trigger the callback on the parent component, letting it know the button was triggered
this.props.callback();
}
}
render() {
return <button onClick={this.onChildButtonClick}>Click me</button>;
}
During initialisation, the Parent component sends a callback method to the child component. Whenever the button is clicked on the child component, the child component triggers the function (callback) given by the parent, essentially running a piece of code on the parent component, which then updates the state with the requested value (could be a string, or anything).
Redux
Redux is another way of doing it, which basically keeps a sort of tracked database that can be used from any component, by pageload - however, that would require an entire tutorial.
Related
I want to change the bottom tab icon from my home screen or another component. I don't know how to achieve it, in Android I can use interface and EventBus but I'm not sure there something equivalent in React-Native, I tried using redux store but didn't work for me I have 5 buttons in the bottom tab bar I want to change the the centre button when I have some check fulfilled from the backend in my home screen.How can I change it from the home screen? any help will be appriciated thank you in advance
You can use ref to access method of other component.
https://facebook.github.io/react-native/docs/direct-manipulation
EDIT:
Sorry for the late reply, the ref method works best if both components are siblings.
Here see this code:
class TestPage1 extends Component {
constructor(props) {
super(props)
this.state={}
};
onDoSomething=()=>{
this.comp2_ref.callThisMethod()
}
render() {
return (
<View>
<Comp1 onDoSomething={this.onDoSomething}/>
<Comp2 onRef={(ref)=>{
this.comp2_ref=ref;
})/>
</View>
)
}
}
class Comp1 extends Component{
render(){
return(<View>
<Button onPress={()=>{
typeof
this.props.onDoSomething==='function'&&this.props.onDoSomething()
}}></Button></View>)
}
}
class Comp2 extends Component{
callThisMethod=()=>{
//do something for comp2 that will be called by comp 1
}
render(){
return(<View></View>)
}
componentDidMount(){
typeof this.props.onRef==='function'&&this.props.onRef(this);
}
}
If they are separate then you can also use consumer and provider concept.
I am looking for pointers where I can start from.
I want to create a react native feedback form which can be displayed with .show method.
for eg:
export class FeedbackComponent extends React.component{
show() {
// define this method in a way so that can be called from outside as FeedbackComponent.show()
// which eventually create a new screen with below rendered View
}
render (){
return <View>Feedback Form</View>
}
}
I should be able to use this Component in any other component as
import FeedbackComponent from './FeedbackComponent'
new FeedbackComponent.show()
I would always start with considering the application state. UI in React is updated whenever the State of our components changes.
In your case I would have to think of the parent context in which your feedback form will need to be displayed. In its simplest form, this context will likely be a parent screen-component within which your FeedbackForm component is either shown or hidden.
I've made a Snack of a simple implementation you can find it here: https://snack.expo.io/#stephos_/show-feedback-form
In my case, the App component is the parent screen-component within which we need to render or not render a FeedbackForm Component.
So I would start with adding the relevant state property to the App (parent screen) component like so:
state = {
feedbackFormVisible : false
}
I would then define a method within the same parent class in order to toggle the state when we need to like so:
handleFeedbackFormVisibility = () => this.setState(prevState => ({feedbackFormVisible:!prevState.feedbackFormVisible}))
This handler takes in the previous state in our parent component and toggles the value of the feedbackFormVisible property (i.e. from false to true).
In my case, I call this handler every time we press a Button component like so:
<Button title="Give Feedback" onPress={this.handleFeedbackFormVisibility}/>
You could however trigger the same handler and update the state of the parent component in any other way (i.e. after a timer expires or after a specific scroll point is passed).
The App Component's render method will then decide if the FeedbackForm component should be displayed based on the value of the feedbackFormVisible in our App Component's state. We achieve this by wrapping our FeedbackForm component within an Elvis Conditional within the render method which will return the the appropriate UI (i.e. either with a visible feedback form or not):
{ this.state.feedbackFormVisible ? () : null}
Below the full App component code:
import * as React from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import FeedbackForm from './components/FeedbackForm';
export default class App extends React.Component {
state = {
feedbackFormVisible : false
}
handleFeedbackFormVisibility = () => this.setState(prevState => ({feedbackFormVisible:!prevState.feedbackFormVisible}))
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
This is the App Parent Component
</Text>
{
this.state.feedbackFormVisible ?
(<FeedbackForm />)
: null
}
<Button title="Give Feedback" onPress={this.handleFeedbackFormVisibility}/>
</View>
);
}
}
And below the Feedback Component code (Notice that the shown/hidden logic is actually handled in the parent component not in here):
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
export default class FeedbackForm extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.paragraph}>
This is the feedback form!
</Text>
</View>
);
}
}
I am trying to get a side menu to open up when I press on a notifications button on the NavigatorIOS React Native component, but the child component doesn't seem to update when the parent's state changes. Thus, pressing on the notifications button is not doing what I want it to do. The parent and child component are as follows. How can I get the child component to update when the parent state changes using NavigatorIOS?
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
rightMenuOpen: false
}
this.rightButtonPress = this.rightButtonPress.bind(this);
}
rightButtonPress() {
this.setState({rightMenuOpen: true});
}
render() {
return (
<NavigatorIOS
initialRoute={{
component: Home,
rightButtonIcon: source=require('./img/notifications.png'),
onRightButtonPress: this.rightButtonPress,
passProps: {index: 1, rightMenuOpen: this.state.rightMenuOpen},
}}
style={{flex: 1}}
/>
)
}
}
class Home extends React.Component {
constructor(props) {
super(props);
}
render() {
const menu = <Switch/>
return (
<View style={styles.body}>
<SideMenu
menu={infoText}
menuPosition="right"
disableGestures={true}
isOpen={this.props.rightMenuOpen}
>
<WebView
source={{uri: 'https://www.michigandaily.com/'}}
bounces={false}
/>
</SideMenu>
</View>
);
}
}
The way you're trying this won't work because changes to the value of passProps won't cause a re-render. What you need is a way to pass a signal to the child from the parent using the Event Emitter or a State Management framework.
Example of how to use the event emitter:
https://colinramsay.co.uk/2015/07/04/react-native-eventemitters.html
I also would recommend using a state management framework like Redux or Mobx (I prefer Mobx for its simplicity).
You can learn more about Mobx here: http://mobx.js.org
I want to access state set in one component which is define in one file lets say one.js,to be access in other component file name Two.js.How to access state of one component in other component.
Do you call/import one.js inside two.js?
if you do, you can pass the state from one.js using props.
EDIT:
To access the state from a page into another one, you'll have to use props. In tthis case, to access the state from one.js into two.js, that's what you could do:
Let's supose that PageOne is a class inside one.js, where you would import two.js:
import PageTwo from 'Two';
...
export default class PageOne extends React.Component{
constructor(props) {
super(props);
this.state = { somethingSomething: 'whatever'};
}
render() {
return (
<View>
<PageTwo propsname = {this.state.somethingSomething}>
</PageTwo>
</View>
)
}
}
In the code above, you're passing the state for PageTwo(two.js), and now to show it:
…
export default class PageTwo extends React.Component{
...
render() {
return (
<View>
{alert(this.props.propsname)}
</View>
)
}
}
I am inserting a rightButton into react-native-router-flux using the renderRightButton api. The problem I ran into is that the rightButton needs to access a method within the component.
class App extends React.Component {
render() {
return(
<Router>
<Scene
key="firstScene"
component={FirstScene}
title="First scene"
rightTitle="Apply"
renderRightButton={this.getRightButton}
/>
</Router>
)
}
getRightButton() {
return(
// someMethodOnFirstSceneComponent lives on the FirstScene component
<View onPress{this.someMethodOnFirstSceneComponent}>
<Text>
Invoke Function from Scene Component
</Text>
</View>
)
}
};
One option would be to put all of the data currently in the state of FirstScene into a redux reducer and then put the someMethodOnFirstSceneComponent on the FirstScene component. However, I am trying to keep state within components and not rely on reducers because from my experience, it keeps things easier to reason about.
I've found a way to do that. Not a very nice solution, but it works. I'm setting onRight method in the component constructor
constructor(props) {
super(props);
this.props.component.onRight = () => {
console.warn("call from my onRight function")}
}
}