Add a chidren at first of component children

Viewed 303

I create an wrapper for Picker component And I want to add a child in condition

I try this code

render() {
    const { children, ...rest } = this.props;

    return (
      <Picker {...rest}>
        {rest.selectedValue === undefined ? (
          <Picker.Item value="1" label="1" />
        ) : null}
        {children}
      </Picker>
    );
  }

And I get this error

TypeError: null is not an object(evaluating 'o.props')

I also try with undefiened instead of null and short circuit condition but I get error in that case too.

Also note If I remove condition and just add an element before children its work. something like this

<Picker.Item value="1" label="1" />
{children}

UPDATED

I found the problem is when condition is false for example this make error

{false && (<Picker.Item value="1" label="1" />)}

expo project https://snack.expo.io/@cooper47/mad-waffle ( change picker and see the error )

I think the problem is when I concat children with undefined ( result of condtion ) because when I try this I get same error

<Picker {...rest}>
   {undefined} // result of short circuit 
   {children} 
</Picker>
  • Why I get this error with conditon and get no error without condition?

  • How I can add an element before this.props.children?

  • Is there anyway add element at first of children? for example children.add(<Picker.Item...>)

I found out actually its a bug in react-native

Here is the relative issue https://github.com/facebook/react-native/issues/25141#issuecomment-498651856

2 Answers

Note: There is no problem with the condition, the error depends on the wrapper (Picker) internal calls.

My guess is that Picker internal calls its children props (expects Picker.Item), it may check your condition props when it falsy and therefore throw an error of undefined props.

<Picker>
  {condition && <Picker.Item value="1" label="1" />}   
  // ^ Picker wrapper may check null.props, undefined.props, false.props etc

  {children}
</Picker>

In this case, make the condition outside the render:

  const conditionChildren = condition ? (
    <> <Picker /> {children} </> ) : (children);
  return {conditionChildren}

How I can add an element before this.props.children?

Use React.createElement or call the component inline:

function ConditionChildren({ children, condition }) {
  return (
    <>
      {condition && <Picker />}
      // or {condition && React.createElement(Picker)}
      {children}
    </>
  );
}

Is there anyway add an element at first of children? for example children.add()

  const addFirstToChildren = [
    React.createElement(Picker),
    ...React.Children.toArray(children)
  ];
return {addFirstToChildren}

Check the demo with the generic solution:

Edit zealous-heyrovsky-exec8

Try below code for PureComponent

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

export default class SelectBox extends React.PureComponent {
    constructor(props) {
    super(props)
    }
    render() {
     const { options, value, onChageText } = this.props
      let Alloptions = options.map((item, key) => {
         return (<Picker.Item label={item.name} value={item.value} key={key} />)
      })
      return (
        <Picker selectedValue={value} onValueChange={onChageText}>
       {/* If you want to add default option here  */}
         {/* <Picker.Item label="Select Location..." value="" /> */}
              {Alloptions}
        </Picker>
     )
    }
}

and your Component Like

<SelectBox
options={[{name:'aaa',value:'11'},{name:'bbbb',value:'22'}]}
value={''}
onChageText={this.selectLocation}
/>
 selectLocation(itemValue, itemIndex) {
...your code
}

Thanks

Related