0

I have a component that will render the child components in an array and the child component would have Input component from Native Base. I would like to validate the input components if they are empty or null. But the code below does not work if the child array have more than 1 child.

Parent

class Parent extends Component {
    validateForms = () => {
      this.child.onSubmitValidate();
    }

    render() {     
       const childArray = stopsArray.map((item, key) => {
          return (
            <View key={key}>
              <Child
                ref={instance => { this.child = instance; }}
                itemIndex={key}
              />
            </View>
          );
        });

        <View style={styles.container}>
          <View style={{ flex: 1 }}>
            {
              childArray
            }
          </View>

          <Button
             onPressAction={() => this.validateForms()}
             buttonText={'PAYMENT'}
          />
        </View>
    }
}

Child

import { Input } from 'native-base';

class Child extends Component {
    onSubmitValidate = () => {
      let error = false;

      ['buildingHouseNo', 'contactName', 'contactPhone']
        .forEach((name, key) => {
          const value = this.state[name];

          const nameValid = `${name}Valid`;

          if (!value || value.trim() === '' || value === null) {
            error = true;

            this.setState({
              [nameValid]: false
            });
          }
        });

      if (!error) {
        this.props.togglePayment();
      }
    }

    handleInput = (title, itemIndex, value) => {
      if (title === 'BuildingHouseNo') {
        this.setState({ buildingHouseNo: value });
      } else if (title === 'RecipientName') {
        this.setState({ contactName: value });
      } else if (title === 'RecipientPhone') {
        this.setState({ contactPhone: value });
      }

      this.validate(title, value);

      this.props.getRecipientInfo({
        index: itemIndex,
        title,
        value
      });
    }

    validate = (title, value) => {
      if (title === 'BuildingHouseNo') {
        if (!value || value.trim() === '' || value === null) {
          this.setState({ buildingHouseNoValid: false });
        } else {
          this.setState({ buildingHouseNoValid: true });
        }
      } else if (title === 'RecipientName') {
        if (!value || value.trim() === '' || value === null) {
          this.setState({ contactNameValid: false });
        } else {
          this.setState({ contactNameValid: true });
        }
      } else if (title === 'RecipientPhone') {
        if (!value || value.trim() === '' || value === null) {
          this.setState({ contactPhoneValid: false });
        } else {
          this.setState({ contactPhoneValid: true });
        }
      }
    }

    render() {
      const itemIndex = this.props.index;

      <View style={styles.container}>
        <View style={styles.borderInput}>
          <Input
            ref={(ref) => { this.buildingHouseNo = ref; }}
            key={itemIndex}
            clearButtonMode='while-editing'
            autoCapitalize='none'
            autoCorrect={false}
            style={styles.inputSearchBorder}
            placeholder='Building Name / House Number'
            onSubmitEditing={() => this.addr2._root.focus()}
            returnKeyType={'next'}
            onChangeText={this.handleInput.bind(this, 'BuildingHouseNo', itemIndex)}
          />
        </View>

        <View style={styles.borderInput}>
          <Input
            key={itemIndex}
            ref={(ref) => { this.contactName = ref; }}
            clearButtonMode='while-editing'
            autoCapitalize='none'
            autoCorrect={false}
            style={styles.inputSearch}
            placeholder='Name'
            value={contactName}
            onSubmitEditing={() => this.contactNo._root.focus()}
            returnKeyType={'next'}
            onChangeText={this.handleInput.bind(this, 'RecipientName', itemIndex)}
          />
        </View>

        <View style={styles.borderInput}>
          <Input
            key={itemIndex}
            ref={(ref) => { this.contactNo = ref; }}
            clearButtonMode='while-editing'
            autoCapitalize='none'
            autoCorrect={false}
            style={styles.inputSearch}
            placeholder='Contact Number'
            value={contactPhone}
            onSubmitEditing={() => this.notesToBunny._root.focus()}
            returnKeyType={'next'}
            onChangeText={this.handleInput.bind(this, 'RecipientPhone', itemIndex)}
          />
        </View>
      </View>
    }
}
Fire Hand
  • 25,366
  • 22
  • 53
  • 76

1 Answers1

2

You are overriding your ref each time you create a new Child component. You can create an array of ref values and loop through them to validate each of them.

constructor() {
  super();

  this.child = [];
{

const childArray = stopsArray.map((item, key) => {
  return (
    <View key={key}>
      <Child
        ref={instance => { this.child[key] = instance; }}
        itemIndex={key}
      />
    </View>
  );
});

//...

validateForms = () => {
  this.child.forEach(child => {
    child.onSubmitValidate();
  })
}
Fire Hand
  • 25,366
  • 22
  • 53
  • 76
bennygenel
  • 23,896
  • 6
  • 65
  • 78
  • i'm getting this error..."undefined is not an object (evaluating '_this.child[key] = instance')" – Fire Hand Mar 21 '18 at 13:34
  • In your constructor function init `this.child = {};` – bennygenel Mar 21 '18 at 13:36
  • another error..."_this.child.forEach is not a function. (In '_this.child.forEach(function (child) { child.onSubmitValidate(); })','_this.child.forEach' is undefined)" – Fire Hand Mar 21 '18 at 13:40
  • i have figured out the cause of the error above..just change the constructor init function to `this.child = [];`, instead of `this.child = {};` – Fire Hand Mar 21 '18 at 14:08