4

Can someone explain me why this doesn't work as I expect to. I'm trying to navigate from a screen to another using react navigation and I want to pass a value from state from a screen to another (I keep my value from state in parent component and also my 2 functions that changes the state value). When I navigate to my child component, I pass value from state and both functions as well.

The main problem is that I don't see any changes on the child screen when I trigger the 2 functions, but when I go back to my parent screen, the changes have been made and they are visible on the screen.

I've tried to use this.forceUpdate() but it is still not working.

Any help?

This is my parent component where I keep the state and the functions that change my state


import React from 'react';
import { Text, View, TouchableHighlight, Image, ScrollView, FlatList } from 'react-native';

export default class Parent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      value: 2
    };
  }

  incrementValue = () => {
    this.setState(prevState => ({
      value: prevState.value + 1
    }));
  };

  decrementValue = () => {
    this.setState(prevState => ({
      value: prevState.value - 1
    }));
  };

  onPressButton = () => {
    this.props.navigation.navigate('Child', {
      value: this.state.value,
      incrementValue: this.incrementValue.bind(this),
      decrementValue: this.decrementValue.bind(this)
    });
  };

  render() {
    return (
      <View>
        <Text>parent component</Text>
        <TouchableHighlight onPress={() => this.onPressButton()}>
          <Text style={{ color: 'red' }}>go to child</Text>
        </TouchableHighlight>
        <Text>state value : {this.state.value}</Text>
      </View>
    );
  }
}

And here this is my child component:


import React from 'react';
import { Text, View, TouchableHighlight, Image, ScrollView, FlatList } from 'react-native';

export default class Child extends React.Component {
  constructor(props) {
    super(props);
  }

  onPressIncrement = () => {
    this.props.navigation.state.params.incrementValue();
    this.forceUpdate();
  };

  onPressDecrement = () => {
    this.props.navigation.state.params.decrementValue();
    this.forceUpdate();
  };

  render() {
    const { navigation } = this.props;
    const value = navigation.getParam('value');
    alert(value);
    return (
      <View>
        <Text>Child component</Text>
        <Text>{value}</Text>
        <TouchableHighlight onPress={() => this.onPressIncrement()}>
          <Text>incrementValue</Text>
        </TouchableHighlight>
        <TouchableHighlight onPress={() => this.onPressDecrement()}>
          <Text>decrementValue</Text>
        </TouchableHighlight>
      </View>
    );
  }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Prutii35
  • 41
  • 1
  • 4

1 Answers1

0

It is normal. You just render your value prop only in first call of Child screen.

There is a lifecycle method named ComponentDidUpdate for your prop changes. It is triggered once one of your prop changes.

For example you can use like this in your Child Screen,

componentDidUpdate(prevProps) {
  const value = navigation.getParam('value');
  console.log('prevProps', prevProps);
  console.log('new value', value);
}

You should see if value state changes in Parent Screen (which you passed as prop to your Child Screen) then ComponentDidUpdate should triggered with new value.

Edit: After triggered componentDidUpdate and access new value. You can use setState for trigger render function.

constructor(props) {
    super(props);
    this.state = {
      value: navigation.getParam('value');
    }
  }

componentDidUpdate(prevProps) {
  const value = navigation.getParam('value');
  this.setState({ value });
}

render() {
    const { navigation } = this.props;
    return (
      <View>
        <Text>Child component</Text>
        <Text>{this.state.value}</Text>
        <TouchableHighlight onPress={() => this.onPressIncrement()}>
          <Text>incrementValue</Text>
        </TouchableHighlight>
        <TouchableHighlight onPress={() => this.onPressDecrement()}>
          <Text>decrementValue</Text>
        </TouchableHighlight>
      </View>
    );
  }

Hope it works.

firats
  • 496
  • 2
  • 7
  • Well, you are right, when I want to increment/decrement the value, it does trigger the componentDidUpdate() function, but for some reason the value remains the same even after the function was triggered :( – Prutii35 Aug 06 '19 at 14:26
  • Yeah, you can re-render it by using `setState` method. Check my edited answer above @Prutii35 – firats Aug 06 '19 at 14:44
  • Ugh, still not working, did you tried it by any chance? – Prutii35 Aug 06 '19 at 15:09
  • As an alternative to `getParam`, you may use `this.props.navigation.state.params`. @Prutii35 – firats Aug 07 '19 at 06:01