2

I have a react-native project in which I want to render a component on a button click .. the buttons are displayed as a bottom bar, in which every button should render a component.

I tried to set the state like this :

constructor(props){
    super(props);
    this.state = { selectedPage : '' }
}

And in my buttons I tried to set the state of each button to a value :

<TouchableOpacity onPress={ () => this.setState({ selectedPage : 'completed }), this._handleCaseView() }> Completed </TouchableOpacity>

Then I tried to change the value of a variable defined in the render() method with default value of an imported component let caseView = <PendingCases />

my _handleCaseView()

_handleCaseView = () => {
    switch (this.state.selectedPage) {
      case "completed":
        this.caseView = <Text> Completed </Text>;
        break;
      case "delayed":
        this.caseView = <Text> Delayed </Text>;
        break;
      case "all":
        this.caseView = <PendingCases />;
        break;
      case "approved":
        this.caseView = <Text> Approved </Text>;
        break;
      case "set-by-doctor":
        this.caseView = <Text> SET BY DOCTOR </Text>;
        break;
      default:
        this.caseView = <PendingCases />;
    }
  }

Then in my render method <View> { this.caseView } </View>

The problem is that the value isn't getting set, is there a simpler approach ?

--UPDATE--

here is my render() function

return (

      <DrawerLayoutAndroid
        drawerWidth={200}
        drawerPosition={DrawerLayoutAndroid.positions.Right}
        renderNavigationView={() => navigationView}
      >

          <View style={{ flex : 1, flexDirection: 'column', backgroundColor: 'rgb(250, 250, 250)' }}>

          <HeaderWText header="Cases" />

          <View style={ styles.pageBody }>

          <View> { this.renderCaseView(this.state.selectedPage) } </View>

          </View>

        </View>

        <View style={{ height: 70, position: 'absolute', bottom: 0, left: 0, right: 0, borderTopColor: 'rgba(0, 0, 0, .2)', borderTopWidth: 1, flex: 1, flexDirection: 'row'}}>
          <TouchableOpacity onPress={ () => this.setState({ selectedPage : "completed" }) } style={{ flex : 1, padding: 5 }}>
            <View style={{ flex : 1, alignItems: 'center'}}>
            <Image style={{ width : 35, height: 35}} source={require('./images/completed.png')} />
            <Text style={{ textAlign: 'center', fontSize: 12}}>Completed</Text>
            </View>
          </TouchableOpacity>
          <TouchableOpacity onPress={ () => this.setState({ selectedPage : "delayed"}) } style={{ flex : 1, padding: 5 }}>
            <View style={{ flex : 1, alignItems: 'center'}}>
            <Image style={{ width : 35, height: 35}} source={require('./images/delayed.png')} />
            <Text style={{ textAlign: 'center', fontSize: 12}}>Delayed</Text>
            </View>
          </TouchableOpacity>
        </View>

      </DrawerLayoutAndroid>

    )

my constructor() and renderCaseView()

    constructor(props) {
    super(props);
    this.state = { selectedPage : 'completed' }
  }

  renderCaseView = (param) => {
    switch (param) {
      case "completed":
        return <PendingCases />;
        break;
      case "delayed":
        return <Text> Delayed </Text>;
        break;
      case "all":
        return <PendingCases />;
        break;
      case "approved":
        return <Text> Approved </Text>;
        break;
      case "set-by-doctor":
        return <Text> SET BY DOCTOR </Text>;
        break;
    }
  }
4
  • You don't have to use setState callback - you can use this kind of logic inside render 'body' (before return) or call function from render (param/switch/return <Component>) Commented Aug 27, 2018 at 11:17
  • Did you put any logs inside the _handleCaseView to make sure that is changing? Maybe is a good idea to use this._handleCaseView() inside your render method Commented Aug 27, 2018 at 11:18
  • @xadm i'm sorry could you explain it a little more ? i'm not sure i quite got your answer Commented Aug 27, 2018 at 11:20
  • Just call {this._handleCaseView()} inside your render method Commented Aug 27, 2018 at 11:25

2 Answers 2

2

You need to wrap your onPress event to return a single function, right now you're returning multiple functions to it.

onPress={ () => {
  this.setState({ selectedPage : 'completed' }); // Your Updater function
  this._handleCaseView()
}

Another thing to note is , since handleCaseView is dependant on state and you're calling them async, therefore you need to call it once the state has finished updating in the setState callback parameter.

onPress={ () => {
      this.setState({ selectedPage : 'completed' }, () => this.handleCaseView());
}
Sign up to request clarification or add additional context in comments.

2 Comments

Few things completed must be enclosed in single quotes quote missing and switch case will be always same because onPress is always setting completed so the switch case always goes to this <Text> Completed </Text>
Thanks, updated, the usage for the updater function would be for the author to decide :).
1

There're a few methods, you can extend render method with logic like this:

render() {
  const ChoosenView = this.state.selectedPage ? <Completed /> : <Delayed />
  // or more complicated vanilla js logic
  // call parametrized method, etc
  // to prepare 'visual parts'

  return (
    <Layout>
      {ChoosenView}
    </Layout>
  )
}

you can refactor _handleCaseView to

renderCaseView = (param) => {
    // you can use Map/object definitions instead of switch
    switch (param) {
      case "completed":
        return <Text> Completed </Text>;
      case "delayed":
        return <Text> Delayed </Text>;
      case "all":
        return <PendingCases />;
      case "approved":
        return <Text> Approved </Text>;
      case "set-by-doctor":
        return <Text> SET BY DOCTOR </Text>;
      default:
        return <PendingCases />;
    }
}

and use it in render directly

{this.renderCaseView(this.state.selectedPage)}

7 Comments

the second method throws me an error of Cannot add child that doesn't have a YogaNode ...
i changed the TouchableOpacity onPress={ ()=> this.renderCaseView('completed') } and in the render i called { this.renderCaseView() } .. i was trying to find another solution ..
grrr... render (returning components) in handler? WHY? in event handler you have only to setState, render will be fired/forced with new, updated state value - it's simple 'flow'
i updated the question .. please could you take a look ?
it can be sth RN related - try 1st method with const ChoosenView = this.renderCaseView(this.state.selectedPage), console.log it's value (and this.state.selectedPage?) - just debug it.
|

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.