Luigi Nator
Luigi Nator

Reputation: 123

Conditional Rendering of child elements in React

I am trying to write a reusable Header Component in React-Native. I want to write it in a ways that the left and right button can be passed as child components. To know where to render which button I want to pass a prop like rightIcon or leftIcon. However I don't know how to access these props.

This is my App.js file

import React from 'react';
import {StyleSheet, TouchableHighlight, View} from 'react-native';
import Header from "./src/Header";
import {Ionicons} from '@expo/vector-icons';

export default class App extends React.Component {
    render() {
        return (
            <View style={styles.container}>
                <Header headerText={"Barcode Scanner"}>
                    <TouchableHighlight righticon>
                        <Ionicons name="md-barcode" size={36} color="white"></Ionicons>
                    </TouchableHighlight>
                </Header>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1
    },
});
And this is the Header Component

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

export default class Header extends React.Component {
    render() {

        const {textStyle, viewStyle, rightButton} = styles;

        return (
            <View style={viewStyle}>
                <Text style={textStyle}>{this.props.headerText}</Text>
                <View style={rightButton}>
                    {this.renderRightChild()}
                </View>
            </View>
        );
    }

    renderRightChild = () => {
        console.log("Check if rightIcon Prop is set");
    }
}


const styles = {
        viewStyle: {
            backgroundColor: '#5161b8',
            justifyContent: 'center',
            alignItems: 'center',
            height: 80,
            paddingTop: 25,
            shadowColor: '#000',
            shadowOffset: {width: 0, height: 2},
            shadowOpacity: 0.2,
            elevation: 2,
            position: 'relative'
        },
        textStyle: {
            color: '#fff',
            fontSize: 20
        },
        rightButton: {
            position: 'absolute',
            top:
                35,
            right:
                20
        }

    }
;

I already tried to use React.Children.toArray but this always throws an error that the request entity is too large.

Thanks for all the answers

Upvotes: 7

Views: 10173

Answers (3)

th3g3ntl3m3n
th3g3ntl3m3n

Reputation: 151

One way to do this is write a Header Component and pass all the things, as props, which you can then access them in Header Components Props like..

    <Header title="HeaderTitle" 
            leftButtonTitle="LeftButton" 
            rightButton={canBeAObjectWithSomeInfo} 
            leftButtonClick={handleClick} /> 

and then in your header component(can be class or a function)

const Header = ({}) => (
  <View>
    <View onPress={this.props.handleClick}>{this.props.leftButton}</View>
    <View>{this.props.title}</View>
    <View onPress={this.props.handleRightClick}>{this.props.rightButton}</View>
  </View>
)

something like this you can have and then you can design header accordingly

Upvotes: 0

Michal
Michal

Reputation: 5220

I guess you can always use a render prop that way you can not only decide whether to render left/right icon component but the component rendering the icon does not even have to know what to render:

The term “render prop” refers to a simple technique for sharing code between React components using a prop whose value is a function.

return (
  <View style={styles.container}>
    <Header
      headerText={"Barcode Scanner"}
      renderRightIcon={() => (
        <TouchableHighlight righticon>
          <Ionicons name="md-barcode" size={36} color="white" />
        </TouchableHighlight>
      )}
    />
  </View>
);

Then you can use call the right icon as a function:

return (
  <View style={viewStyle}>
    <Text style={textStyle}>{this.props.headerText}</Text>
    {renderLeftIcon && (
      <View style={leftButton}>
        {renderLeftIcon()}
      </View>)
    }
    {renderRightIcon  && (
      <View style={rightButton}>
        {renderRightIcon()}
      </View>)
    }
  </View>
);

Upvotes: 4

Isaac Sekamatte
Isaac Sekamatte

Reputation: 5598

You render both components, the right and left and you put an if condition inside state.

Header Component render method

render() {
  const { leftOrRight } = this.props // right - true, left - false
  return(
    ...
    { leftOrRight ? <RightIcon />  : <LeftIcon />}
  );

}

Inside Component that calls Header

import Header from './somepath ...';

class Something extends React.Component {
   this.state = { leftOrRight }

   render() {
     return(
        <Header leftOrRight = {this.state.LeftOrRight}/>
     );
   }
}

You could have a function that sets leftOrRight in your parent class

Upvotes: 2

Related Questions