0

How can I force reload certain or all react Components when a particular value is selected using Picker?

    import React from 'react';
    import { Picker, Text, View } from 'react-native';

    export default class Test extends React.Component {
      render(){
        return (
          <View>
            <TestComponent />
            <Text>
              {defaultKey + ' from defaultKey from main class'}
            </Text>
          </View>
        );
      }
    }

    let myArr = [
      {
        "key": "key0",
        "value": "value0"
      },
      {
        "key": "key1",
        "value": "value1"
      }
    ];

    let defaultKey = "key0";

    class TestComponent extends React.Component {
      constructor (props){
        super(props);
        this.state = {
          selectedValue : "value0",
          PickerValueHolder : "value0"
        }
      }
      render(){
        return (
          <View>
            <Picker
              selectedValue ={ this.state.PickerValueHolder }
              onValueChange ={ (itemValue, itemIndex) => {
                  this.setState({ PickerValueHolder: itemValue });
                  defaultKey = myArr[itemIndex].key;
                  defaultIndex = itemIndex;
                }
              } 
            >
              { myArr.map((item, key)=>(
                <Picker.Item label={ item.key } value={ item.value } key={ key } />)
              )}
            </Picker>
            <Text>
              {defaultKey + ' from defaultKey from TestComponent'}
            </Text>
          </View>
        );
      }
    }

In this case, the <Text> in the default class is not reloading. How do I make it reload? And how can I force reload Imported components as well?

acagastya
  • 323
  • 2
  • 14

2 Answers2

1

React Components renders / refresh whenever state / props changes. If you want to re render current component change it's state. If you want to render the child component change it's props. If you want to re render the parent component use a callback and modify the state in callback.

krishnan
  • 782
  • 1
  • 9
  • 20
0

You could use global state management like redux, but if you're unfamiliar with that, you can send a handler into the Test Component as a callback to the Parent via the props.

Changing current component value use

this.state

Changing a child component value use and pass the prop in by

Inserting Props to child:

<ChildComponent prop1={value}/>

Getting the value from the child component:

this.props.prop1

Updating the Parent state is similar to the Above but requires the prop to be a function passed from the parent.

handler () {// some function in parent component}
<ChildComponent prop1={this.handler}/>

It would mean it would look something like below:

import React from 'react';
import { Picker, Text, View } from 'react-native';



export default class Test extends React.Component {

  constructor(props) {
    super(props)
    this.handler = this.handler.bind(this);
    this.state = {
      defaultKey : "somevalue"
    };
  }

  handler(value) {
    this.setState({
      defaultKey: value
    })
  }

  render(){
    return (
      <View>
        <TestComponent handler={this.handler}/>
        <Text>
          {this.state.defaultKey + ' from defaultKey from main class'}
        </Text>
      </View>
    );
  }
}

let myArr = [
  {
    "key": "key0",
    "value": "value0"
  },
  {
    "key": "key1",
    "value": "value1"
  }
];

let defaultKey = "key0";

class TestComponent extends React.Component {
  constructor (props){
    super(props);
    this.state = {
      selectedValue : "value0",
      PickerValueHolder : "value0"
    }
  }
  render(){
    return (
      <View>
        <Picker
          selectedValue ={ this.state.PickerValueHolder }
          onValueChange ={ (itemValue, itemIndex) => {
              this.setState({ PickerValueHolder: itemValue });
              defaultKey = myArr[itemIndex].key;
              defaultIndex = itemIndex;
              this.props.handler(defaultKey);
            }
          } 
        >
          { myArr.map((item, key)=>(
            <Picker.Item label={ item.key } value={ item.value } key={ key } />)
          )}
        </Picker>
        <Text>
          {defaultKey + ' from defaultKey from TestComponent'}
        </Text>
      </View>
    );
  }
}

UPDATE:

The OP has asked about why to use redux (as some of the components are not nested through the Test class.

What is redux?

Redux is a predictable state container for JavaScript apps.It helps you write applications that behave consistently.

Check out the docs here: https://redux.js.org/

Essentially, you've entered an issue a lot of people face when building an application that needs to share state between components in React/React Native. In every component you have a local state (this.state) - Redux includes a global App State, therefore in your classes where you change your default value, you can update the global store (which all components have access to). The value which you display the defaultValue would be from the global store.

Essentially, components which are not related to each other, will not know about each others state you'll need to use a global store such as redux. I suggest you do some research on the best technique for you. One way you could achieve it at present would be to wrap the whole application in a parent component and pass the props down from there, such as

-- ParentComponent (set state here)
   -- ChildComponent1 (Pass Props)
      -- ChildComponentOf1 (Pass Props)
   -- ChildComponent2 (Pass Props)

For some further reading check out some posts here:

How to update parent's state in React?

How to share state among multiple scenes of a Navigator in React-Native

JRK
  • 3,686
  • 1
  • 13
  • 19
  • There are many other components in the app, of which some are not directly connected with these two components. How would I change those? And how can I use redux to solve the issue, as you suggested? – acagastya Sep 15 '18 at 21:50
  • @acagastya I've updated my answer for you. I hope it helps – JRK Sep 15 '18 at 22:54