2

I'm creating a simple custom component that will set dynamic height and width within text.

Class CustomComponent extends React.Component{
  render(){
    if(this.props.children){
      if(this.state.isLoading){
        console.log(this.props.children)

        //Here i want to know what JSX is passing

        return(
          <View>
            <ActivityIndicator size={'large'}/>
          </View>
        )
      }
      return(
        <ImageBackground
          source={this.props.source}
        >
          {this.props.children}
        </ImageBackground>
      )
    } else if(this.state.isLoading){
      return(
        <View>
          <ActivityIndicator size={'large'}/>
        </View>
      )
    } else return(
      <Image
        source={this.props.source}
      />
    )
  }
}
//Use with text
<CustomComponent>
  <View>
    <Image {passing image} />
    <Text>Sample</Text>
  </View>
</CustomComponent>

But now i need to handle if the children only passing <Images/> with <Text> or not, any suggestion?

keikai
  • 14,085
  • 9
  • 49
  • 68
flix
  • 1,688
  • 3
  • 34
  • 64

2 Answers2

2

If there are multiple elements, the children passed by props is actually an array,

children:  

[0]: <Image {passing image} />
[1]: <Text>Sample</Text>

If you arrange the child elements like below and the structure is fixed.

  <View>
    <Image {passing image} />
    <Text>Sample</Text>
  </View>

You can visit the children array of the children via (with optional chaining perhaps)

this.props.children.props.children[1].type === 'Text'

which means in your situation, you can check the length of it, or whether the second element's type fit Text, to find out if the Text component is been passed or not.

Try it online:

Edit nervous-monad-jfkhz


Update

If we want the full view of the children, console without the attribute type would be good.

this.props.children.props.children[1]
type: "div"
key: null
ref: null
props: Object
_owner: FiberNode
_store: Object
keikai
  • 14,085
  • 9
  • 49
  • 68
  • actually i want to get full of JSX from children passed in my `CustomComponent`, so in above case I want to console `Sample` in my `CustomComponent`, is it possible? – flix Mar 16 '20 at 03:41
  • @flix I don't think this is related to the question title, as well as you can use `ref` or `createElement` to achieve that, based on this answer – keikai Mar 16 '20 at 04:03
  • @flix And what you mean `Sample` is the same with `children`, it's just different format, kindly check the related document here https://reactjs.org/docs/introducing-jsx.html – keikai Mar 16 '20 at 04:12
0

When we pass a prop as children then children can be any React.Node which makes it hard to identify what children exactly are and also is not reliable. Checking children.props.children[1].type is not reliable as it might not work if someone reorder the structure of the children.

In your case we need to make the CustomComponent accepts two props:

1- image

2- text

and make it nullable for any that is not required. Then in your customComponent we can have an access to an actual image and text component. If you want to access HTMLElement not node you can pass ref to image and text component and then you can access the current value in CustomComponent

Example: Functional component with inline props

const CustomComponent = ({ image, text }) => {
 if (image !== null) {
    ...
 }
 if (text !== null) {
    ...
 }
 return (
   <View>
    {image}
    {text}
   </View>
 )
} 

Then you use it like this

 <CustomComponent 
  image={<Image src='' />}
  text={<Text>Sample</Text>} 
 /> 
Matin Kajabadi
  • 3,414
  • 1
  • 17
  • 21