2

I have a requirement of showing a tab like behavior inside a react native Modal

I have started by creating a state variable selectedSub which is initialized with value 'from'

Now my modal has 2 TouchableHighlight as below

_availabiltyModal() {
return (
<TouchableHighlight
    onPress={() => { this.setState({ selectedSub: 'from' }) }}
    activeOpacity={0.9}
    style={[styles.tab, this.state.selectedSub == 'from' && styles.active]}>
        <RkText rkType="header" style={this.state.selectedSub == 'from' && styles.activeText}>From</RkText>
</TouchableHighlight>
<TouchableHighlight
    onPress={() => { this.setState({ selectedSub: 'to' }) }}
    activeOpacity={0.9}
    style={[styles.tab, this.state.selectedSub == 'to' && styles.active]}>
        <RkText rkType="header" style={this.state.selectedSub == 'to' && styles.activeText}>To</RkText>
</TouchableHighlight>
{this._renderPicker()}
)}

These two are responsible to change the state param selectedSub as required.

Based on this state param i am conditionally showing another component i made and imported as below

_renderPicker() {
    if (this.state.selectedSub == 'from') {
        return <TimePicker screenProps={{ time: this.state.selectedAvailabilty.from }} />
    } else {
        return <TimePicker screenProps={{ time: this.state.selectedAvailabilty.to }} />
    }
}

I have called this function in the Modal below the TouchableHighlight's

Now as per the RN docs when ever the state variable is updated with this.setState() method the component should re-render. Everything else is working fine (TouchableHighlight styles changing) and also the updates to the state are reflecting in the console. But the _renderPicker function does not return the changed view and is always stuck on the view which was set when the parent was initialized as pointed earlier.

Could somebody help me point the problem here which i might have been overlooking. Also on the side note all this calls are actually directly made outside the main render() method. Could that be a possible issue

------update------ here is the complete reference

 render() {
    return({this._availabiltyModal()}
    <View style={appStyles.tagsWrapper}>
        {this.state.week.map((day, i) => {
            return (
                <TouchableHighlight
                    key={i}
                    activeOpacity={0.9}
                    style={[appStyle.mr10, appStyle.mb10]}
                    onPress={() => {
                       this.setModalVisible(true, day);
                    }}>
                    <Text style={appStyle.tag}>{day}</Text>
                </TouchableHighlight>
            )
        })}
     </View>
    )
}
4
  • I think the problem is really with the modal. As just observed if i hide the the modal and then show it again my _renderPicker() method is able to show the updated component view. Does this mean that the modal does not get re-rendered on state changes Commented Nov 8, 2018 at 11:24
  • Actually if the state is update the functions depending on that will never get recalled. As your case you have a function that returns a view. Every thing in the render function should re render be it Modal Commented Nov 8, 2018 at 11:41
  • Makes sense! But the problem is even if i put the _renderPicker() content inside the modal which is a part of the main render function the view does not re render as required until the modal is closed and opened again. Commented Nov 8, 2018 at 13:43
  • I think it has something to do with the implementation of Modal component from react-native. Commented Nov 8, 2018 at 13:47

1 Answer 1

1

Move the _renderPicker method inside the render() method like...

render() {
...
{this._renderPicker()}
...
} 

Looking at the code of the MODAL component from react-native

render(): React.Node {
    ....
    const innerChildren = __DEV__ ? (
      <AppContainer rootTag={this.context.rootTag}>
        {this.props.children}
      </AppContainer>
    ) : (
      this.props.children
    );

    return (
      <RCTModalHostView
        ....>
        <View style={[styles.container, containerStyles]}>
           {innerChildren} 
        </View>
      </RCTModalHostView>
    );
  }

The state you are changing are of the component that use the modal component thats render its children through the upper function.. when the state update it only re render the component whose state is updated.. so somewhere down rendering child inside component it does not get re render until force re render is applied.

Here is an helpful article to further explain how exactly this functions, forcefully re-rendering the child component

Sign up to request clarification or add additional context in comments.

5 Comments

Hey @Ahsan my {this._renderPicker()} has to be a part of the the modal which is already getting inside the render method. Also just for the information putting it in the render method did not really make any update.
Can you update the question and provide complete code of your render method ... or atleast all code related to your problem
hey sorry about that, I have update the code. The render function has the this._availabiltyModal() which has the tow TouchableHighlight's and then follows with the this._renderPicker() method
Just edited the answer... this is my observation after looking the implementation and with the knowledge i have.
You are right, In react a child component in the nested components is never going to re-render until the props of the child component are updated with the help of componentWillReceiveProps() for say. Thanks for the help! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.