Navigation - Pass variable to other files - react-native

I'm new on React-Native and it's my first React-Native app. However, I have already some problems.
I want to pass a variable from one class (Home.js) to an another. (Is it possible without using the composent in the render() fonction ?)
##### Home.js #####
class Home extends Component {
constructor(props) {
super(props);
this.state = {direction: "defaultvalue"};
}
getCurrentDirection() {
return this.state.direction;
}
render() {
/***..... some elements ..*/
}
}
export default Home
And
#### Two.js ####
import Home from './Home'
/** SOME CODE **/
const DrawerOptions = {
initialRouteName: Home.getCurrentDirection(),
contentComponent: CustomDrawerContentComponent,
drawerWidth: 300,
};
However it doesn't work... How to resolve it ? I have already try some solutions as declare the getCurrentDirection as static but nothing.
In addition, it seems to be a specific case because DrawerOptions is not a class. Could you please, add to your response also, how make it if I want to obtain the variable into the class Two.js ?
I meant if Two.js was for example :
##### Two.js #####
class Two extends Component {
var myvariable = Home.getCurrentDirection();
render() {
/***..... some elements ..*/
}
}
Thanks a lot in advance

A recommendable way of accessing the state from a component into another is to use (in this case) the Home component as a parent of Two component. This way you don't have to trigger a function to access the Home's state. On each time when the state of the parent (in this case) component will be updated, the Two component will receive the updated property (direction). If you want to call a function from Two component, you have to pass it a function as a property (changeCurrentDirection) that will call back the function you want to trigger from Home component.
So you would have something like this:
class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
direction: "defaultValue"
};
}
changeCurrentDirection() {
this.setState({
direction: "valueChanged"
})
}
render() {
let state = this.state;
return (
<Two
direction={state.direction}
changeCurrentDirection={() => this.changeCurrentDirection.bind(this)}/>
)
}
}
class Two extends React.Component {
render() {
let props = this.props;
return (
<div>
<h3>{props.direction}</h3>
<button onClick={props.changeCurrentDirection()}>Change value</button>
</div>
)
}
}
React.render(<Home/> , document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.0/react.min.js"></script>
<div id="app"></div>
Additional info you can find here.
Also, if you want to have a good management of the state of your components, my advice for you is to use redux. Using this library you can easily connect the component's actions and properties that can further be accessible from other files where you can manage them.

Related

React Native: How can I redirect after login to different pages depending on the type of account of a user?

I'm building a react native app using expo and I would like to know how I can send a "UserTypeA" to Homepage and send a "UserTypeB" to Profile upon login.
I have a UserTypeA tab navigator and a UserTypeB tab navigator, with just 2 pages that will be see able by both accounts.
I have my UserTypeA data and UserTypeB data in separate tables so I can identify which user has which type.
Sorry if it's not clear this is my first question.
Thank you for your help!
In your apps main render method, you could do something like this.
Basically, you will listen to your redux state and switch main screen depending on the user type.
class MyApp extends PureComponent {
constructor(props) {
super(props);
}
render() {
const { auth } = this.props;
if (auth.userObj.type1) {
return <Type1MainComponent />;
}
if (auth.userObj.type2) {
return <Type2MainComponent />;
}
return <LoginScreen />;
}
}
function mapStateToProps(state) {
const { auth } = state;
return { auth };
}
export default connect(mapStateToProps)(MyApp);

how to call fetch in a sub component in react native?

I saw some tutorials online and majority of the examples are using
a class component e.g
export default class App extends Component {
constructor() {
super();
//set state here and data source
}
componentDidMount() {
//get json data here
}
render() {
return(
blah blah blah
)
}
}
what if I want a sub component to have a functionality that calls fetch , how to do it ?
//NewComponent.js
//this is my sub component
const NewComponent = () => {
return(
<FlatList />
//I want a list of data here
)
}
const getData = () => {
//call fetch here
}
export default NewComponent
so in my second code snippet how to call the getData in order for me to display the data inside the NewComponent?
You have several options. Personally I would go for #3
You can make your sub component a class and use React's lifecycle method such as componentDidMount
You can move getData function to another javascript module. Then import and call it from parent component. Pass the result as props down into the sub component.
Use React's Effect Hook. Pay attention to the section Optimizing Performance by Skipping Effects also.
Hope that helps.

how to manage component mount and unmount to update state values?

I would like to know how to manage state property when the component mounts and unmounts.
I have a lot of different components in my application to maintain the application flow. I know about function componentdidmount and componentWillUnmount. and I also tried the solution about _isMounted=true on componentdidmount function and check _isMounted properties value when I update setState and then update _isMounted=false on componentWillUnmount function.
but this won't work when more two components come in the picture.
For example following links:
https://www.robinwieruch.de/react-warning-cant-call-setstate-on-an-unmounted-component/
Is there a way to check if the react component is unmounted?
as per the example, I have made a common class which will update the value of a component in setMounted function and will return value in getMounted function to validate component is mounted or not. These methods work correctly on a single screen when I call another screen from a stack and update some values then comes back on the previous page and refresh page it will ismount=false.
class Mount {
isMounted=false;
getMounted=()=>{
return isMounted;
}
setMounted=mounted=>{
isMounted=mounted;
}
}
var mount=new Mount();
export default mount;
class example extends component{
componentDidMount=async()=>{
mount.setMounted(true);
await this.loadScreen();
this.willFocusSubscription = this.props.navigation.addListener(
'willFocus',
async() => {
await this.loadScreen();
}
);
}
loadScreen=async()=>{
//some other stuff
if(mount.getMounted()){//second time value is false
this.setState({value:'value'});
}
}
componentWillUnmount() {
mount.setMounted(false);
}
//renderview where i call example2 on buttonclick
}
class example2 extends component{
componentDidMount=async()=>{
mount.setMounted(true);
await this.loadScreen();
}
loadScreen=async()=>{
//some other stuff
if(mount.getMounted()){
this.setState({value:'value'});
this.props.navigation.goBack();
}
}
componentWillUnmount() {
mount.setMounted(false);
this.willFocusSubscription.remove();
}
}
It was showing following warning before using mount functions:
Can't perform a React state update on an unmounted component
You are creating only a single instance of your Mount class that is exported and shared across every instance of every component. You will need to create a new instance of Mount for each component instance:
class Mount {
...
}
// export the Mount class
export default Mount;
class example extends component{
constructor(props) {
super(props);
// create an instance of Mount for each component instance
this.mount = new Mount();
}
componentDidMount=async()=>{
this.mount.setMounted(true);
await this.loadScreen();
this.willFocusSubscription = this.props.navigation.addListener(
'willFocus',
async() => {
await this.loadScreen();
}
);
}
loadScreen=async()=>{
//some other stuff
if(this.mount.getMounted()){//second time value is false
this.setState({value:'value'});
}
}
componentWillUnmount() {
this.mount.setMounted(false);
}
//renderview where i call example2 on buttonclick
}
Notice the addition of the constructor and the use of this.mount instead of mount throughout.

It is possible force screen update after navigation.goBack() in React Native?

Exists some way to do this?
When I use { navigation.goBack() } my changes wasn't does updated in the before screen, but using navigate('MyObject', params ) the changes will be made without additional code to receive the changes.
There are 2 ways I can think of for you to do this. The first is to use Redux and the second is to pass a function to the next screen that will update the previous screen. Example (for the second method) are below:
export default class screenA extends Component {
constructor(props) {
super(props);
this.state = {value: 0};
}
updateValue=(val)=>{
this.setState({value: val});
}
openScreenB=()=>{
this.props.navigation.navigate('screenB', {
updateValue: this.updateValue,
});
}
}
export default class screenB extends Component {
updateClassAValue() {
const {params} = this.props.navigation.state;
params.updateValue(20);
this.props.navigation.pop();
}
}
For Redux, I can't really say much about it since I haven't used it that much. However, it's made for this kind of purpose of sharing values between screen and easily updating the values.

Pass variable from one component to another one in react native

I have ChooseLevel component which has many buttons. Once I click a button onLevelSelected function is being called and it call action creator which will return an action type, moreover it will redirect me to qPage component. In qPage component I make some calculation and I put the result in total variable.
Here's my code:
ChooseLevel.js
class ChooseLevel extends Component {
constructor(props) {
super(props);
}
onLevelSelected(levelNumber) {
this.props.levelSelected(levelNumber);
}
render(){
<Button key={1} onPress={this.onLevelSelected.bind(this, 1)}>
<Button key={2} onPress={this.onLevelSelected.bind(this, 2)}>
<Button key={3} onPress={this.onLevelSelected.bind(this, 3)}>
....
}
}
My action creator looks like this:
import { Actions } from 'react-native-router-flux';
export const levelSelected = (levelNumber) => {
return (dispatch) => {
dispatch({
type: 'level_selected',
payload: levelNumber
});
Actions.qPage(); // redirects me to qPage component
};
};
qPage.js
class qPage extends Component {
constructor(props){
...
}
calc(){
.... some calculation
total = result of previous calculation
}
render(){
....
....
}
}
How do I pass total variable from qPage to ChooseLevel page?
What you need to do is, i will go step by step:
1) create one more action and pass calculated value inside that action.
2) access that calculated value through props(reducer)
3) You can use componentWillUpdateProp(nextprops), Inside this fuction assign this new prop to the state of the class.
Cheers :)