Formik & Yup - поле, не добавляемое в props.errors при использовании Yup.object (). Required () - PullRequest
0 голосов
/ 26 сентября 2019

По какой-то причине мое поле GroceryStore никогда не добавляется к объекту props.errors formik, несмотря ни на что.Это обязательное поле, так что может быть причиной того, что это поле никогда не будет добавлено в объект formik props.errors, когда поле не определено?GroceryStore действительно появляется в объектах props.touched и props.values formik.

Поле задается в <LocationAutocomplete в коде ниже:

class AddGroceryItemView extends React.Component {
  render() {
    const {
      values,
      handleSubmit,
      setFieldValue,
      errors,
      touched,
      setFieldTouched,
      isValid,
      isSubmitting
    } = this.props

    return (
      <Container>
        <VepoHeader title={'Add Vegan Grocery Product'} />
        <Container style={container}>
          <ScrollView
            keyboardShouldPersistTaps="always"
            style={viewStyle(this.props.locationListDisplayed).scrollView}>
            <LocationAutocomplete
              label={'Grocery Store'}
              placeholder={'Enter Grocery Store'}
              setFieldTouched={setFieldTouched}
              setFieldValue={setFieldValue}
              name="GroceryStore"
              required
              error={errors.GroceryStore}
              touched={touched.GroceryStore}
            />
            <View style={viewStyle().detailsContainer}>
              <Input
                label={'Product Name'}
                onTouch={setFieldTouched}
                value={values.Name}
                placeholder="Enter Name"
                name="Name"
                required
                error={touched.Name && errors.Name}
                deleteText={setFieldValue}
                onChange={setFieldValue}
              />
              <Input
                label={'Product Brand'}
                value={values.Brand}
                onTouch={setFieldTouched}
                error={touched.Brand && errors.Brand}
                placeholder="Enter Brand"
                name="Brand"
                required
                onChange={setFieldValue}
                deleteText={setFieldValue}
              />
              <View>
                <Input
                  label={'Product Description'}
                  value={values.Description}
                  placeholder="Enter Description"
                  multiline={true}
                  required
                  onTouch={setFieldTouched}
                  error={touched.Description && errors.Description}
                  numberOfLines={4}
                  name="Description"
                  deleteText={setFieldValue}
                  onChange={setFieldValue}
                />
                <Input
                  isValid={true}
                  isPrice={true}
                  label={'Product Price'}
                  value={values.Price}
                  onTouch={setFieldTouched}
                  error={touched.Price && errors.Price}
                  placeholder="Enter Price"
                  name="Price"
                  deleteText={setFieldValue}
                  onChange={setFieldValue}
                />
                <CategoriesMultiselect.View
                  error={errors.Categories}
                  setFieldValue={setFieldValue}
                  setFieldTouched={setFieldTouched}
                  touched={touched.Categories}
                  name="Categories"
                  required
                  label="Product Categories"
                  categoryCodes={[CategoryEnums.CategoryCodes.Grocery]}
                />
                <ImagePicker
                  label="Product Image"
                  setFieldValue={setFieldValue}
                  name="Image"
                />
              </View>
            </View>
          </ScrollView>
        </Container>
        <Button.View
          title="submit"
          onPress={handleSubmit}
          label={'GO!'}
          disabled={!isValid || isSubmitting}
          loading={isSubmitting}
        />
      </Container>
    )
  }
}

const container = {
  flex: 1,
  ...Spacing.horiz_pad_md_2,
  backgroundColor: Colors.grey_lite,
  flexDirection: 'column'
}

const formikEnhancer = withFormik({
  validationSchema: Yup.object().shape({
    Name: Yup.string().required(),
    Brand: Yup.string().required(),
    GroceryStore: Yup.object()
      .shape({
        city: Yup.string(),
        latitude: Yup.number(),
        longitude: Yup.number(),
        name: Yup.string(),
        place_id: Yup.string(),
        street: Yup.string(),
        street_number: Yup.string(),
        suburb: Yup.string()
      })
      .required(),
    Image: Yup.object().shape({
      uri: Yup.string(),
      name: Yup.string(),
      type: Yup.string()
    }),
    Categories: Yup.array()
      .min(1, 'Please select at least 1 Category')
      .required(),
    Description: Yup.string()
      .min(9)
      .required(),
    Price: Yup.string().matches(
      /^\d+(?:\.\d{2})$/,
      'Price must contain 2 decimal places (cents) e.g. 4.00'
    )
  }),
  isInitialValid: false,
  mapPropsToValues: () => ({
    Name: '',
    Brand: '',
    Description: '',
    Price: '',
    Categories: [],
    GroceryStore: {},
    Image: {}
  }),
  handleSubmit: (values, { props }) => {
    handleSubmit(values, props)
  },
  displayName: 'AddGroceryItemView'
})(AddGroceryItemView)

// $FlowFixMe
const AddGroceryItemViewComponent = connect(
  mapStateToProps,
  mapDispatchToProps
)(formikEnhancer)

export default AddGroceryItemViewComponent

Я недумаю, что необходимо увидеть реализацию LocationAutocomplete, потому что мы должны увидеть ошибку в props.errors для GroceryStore независимо от того, что, если значение не введено.Но тут все равно:

let PresentationalLocationView = (props: PresentationalLocationViewProps) => {
  return (
    <View>
      <Input
        isValid={props.isValid}
        placeholder={props.placeholder}
        label={props.label}
        value={props.location.searchText}
        required
        name={props.name}
        error={props.touched && props.error}
        onTouch={props.setFieldTouched}
        onChange={(name, text) => {
          props.onChange(text)
          if (!text) {
            props.updateLocationAutocompletePlace({})
            props.updateShopShouldHideResults(true)
            props.updateLocationListDisplayed(false)
          }
        }}
        deleteText={() => {
          props.onChange('')
          props.updateLocationAutocompletePlace({})
          props.updateShopShouldHideResults(true)
          props.updateLocationListDisplayed(false)
        }}
      />
      <View style={autocompleteStyle.listView(props)}>
        <FlatList
          keyboardShouldPersistTaps={true}
          data={props.autocompleteResults.predictions}
          renderItem={(listItemValue) =>
            renderAutocompleteItem(props, listItemValue)
          }
        />
      </View>
    </View>
  )
}

// eslint-disable-next-line flowtype/no-weak-types
class ShopView extends React.Component<LocationViewProps | any> {
  componentDidUpdate(prevProps) {
    if (!isEqual(this.props.locationValue, prevProps.locationValue)) {
      this.setFormLocation(this.props)
    }
  }

  setFormLocation = (props) => {
    if (props && props.setFieldValue) {
      props.setFieldValue(props.name, props.locationValue)
    }
  }

  render(): React.Node {
    return (
      // $FlowFixMe
      <PresentationalLocationView
        value={this.props.location.searchText}
        location={this.props.location}
        placeholder={this.props.placeholder}
        isValid={this.props.isValid}
        label={this.props.label}
        required
        name={this.props.name}
        touched={this.props.touched}
        error={this.props.error}
        setFieldTouched={this.props.setFieldTouched}
        onTouch={this.props.onTouch}
        updateLocationAutocompletePlace={
          this.props.updateLocationAutocompletePlace
        }
        updateShopShouldHideResults={this.props.updateShopShouldHideResults}
        updateLocationListDisplayed={this.props.updateLocationListDisplayed}
        autocompleteResults={this.props.location.searchResults}
        shouldHideResults={this.props.location.shouldHideResults}
        onListItemSelect={(shop) => {
          this.props.getLocationAutocompletePlaceDetails(shop.place_id)
          this.props.updateLocationAutocompleteSearchText(shop.description)
          this.props.updateShopShouldHideResults(true)
          this.props.updateLocationListDisplayed(false)
        }}
        onChange={(text) => onChange(this.props, text)}
      />
    )
  }
}
...