【问题标题】:How to use Checkbox and Radio Buttons with Formik, Yup, Ui Kitten in React Native如何在 React Native 中使用 Formik、Yup、Ui Kitten 的复选框和单选按钮
【发布时间】:2019-12-16 08:38:51
【问题描述】:

我在我的应用中使用 Formikyup 作为表单。我无法用 Formik 实现 checkbox,实现了这个solution,但它不适用于我。以下是我迄今为止尝试过的代码。在我单击复选框时实施此解决方案后,表单变得无效并且提交按钮不会调用handleSubmit 方法。我也尝试使用React Native Elements 而不是UI Kitten,但结果是一样的。

const validationSchema = Yup.object().shape({

  service_charge_status: Yup.boolean(),//.oneOf([true], 'Please check the agreement'),
  documents_status: Yup.boolean(), //.oneOf([true], 'Please check the agreement'),
  security_number: Yup.string()
    .label('Security Number *')
    .required('Security Number is required'),
  note: Yup.string().label('Note')


    })
    handleSubmit = (values: any) => {
    console.log('AD Values', values);
  }

  render() {
    return (
      <Formik
        initialValues={{
          // id: '',
          service_charge_status: false,
          documents_status: false,
          security_number: '',
          note: '',
          security_personel_number: ''
        }}
        onSubmit={values => { this.handleSubmit(values) }}
        validationSchema={validationSchema}
      >
        {({ handleChange,
          values,
          handleSubmit,
          errors,
          isValid,
          isSubmitting,
          touched,
          handleBlur,
          setFieldValue }
        ) => (<ScrollView>
          <Header
            noBackButton={true}
            navigation={this.props.navigation}
            title="Approve Request"
          />
          <Layout style={{ padding: 20 }}>
            <View style={{ marginVertical: 5 }}>
              <Text category="p1" style={{ marginVertical: 5 }}>
                Requester Type
            </Text>
              <View style={{ flexDirection: 'row' }}>
                <RadioGroup
                  selectedIndex={this.state.requestTypeIndex}
                  onChange={(index) => this.setState({ requestTypeIndex: index })}                >
                  <Radio
                    text="New Issue"
                    textStyle={styles.labelColor}
                    // checked={values.is_new_issue}
                    status="warning"
                  />
                  <Radio
                    text="Replacement"
                    textStyle={styles.labelColor}
                    // checked={values.is_replacement}
                    // onChange={handleChange('is_replacement')}
                    status="warning"
                  />
                </RadioGroup>
              </View>
            </View>
            <View style={{ marginVertical: 5 }}>
              <Text category="p1" style={{ marginVertical: 5 }}>
                Check List
            </Text>
              <Layout style={{ marginVertical: 6 }}>
                <CheckBox

                  text="Service Charges"
                  textStyle={styles.labelColor}
                  status="warning"
                  checked={values.service_charge_status}
                  onChange={(val) => setFieldValue('service_charge_status', !values.service_charge_status)}

                />
              </Layout>

              <Layout style={{ marginVertical: 6 }}>
                <CheckBox

                  text="Documents Verification"
                  textStyle={styles.labelColor}
                  status="warning"
                  checked={values.documents_status}
                  onChange={(val) => setFieldValue('documents_status', !values.documents_status)}
                />
              </Layout>
            </View>
            <View style={{ marginVertical: 5 }}>
              <Text category="p1" style={{ marginVertical: 5 }}>
                Security Personel Number *
            </Text>
              <Input
                placeholder="Enter Security personel number"
                size='small'
                multiline={true}
                status={touched.security_personel_number ? !errors.security_personel_number ? 'success' : 'danger' : 'warning'}
                caption={(touched.security_personel_number && errors.security_personel_number) ? errors.security_personel_number : ''}
                value={values.security_personel_number}
                onChangeText={handleChange('security_personel_number')}
              />
              <Text category="p1" style={{ marginVertical: 5 }}>
                Note *
            </Text>
              <Input
                placeholder="Enter Note"
                size='small'
                multiline={true}
                status={touched.note ? !errors.note ? 'success' : 'danger' : 'warning'}
                caption={(touched.note && errors.note) ? errors.note : ''}
                value={values.note}
                onChangeText={handleChange('note')}
              />
            </View>

            {this.state.formSpinner &&
              <View style={styles.centeredContentViewStyle}>
                <ActivityIndicator animating size="small" color="#fbaf3a" />
              </View>}

            {this.state.error ?
              <View style={styles.centeredContentViewStyle}>
                <Text style={styles.errorMessageStyle}>{this.state.error}</Text>
              </View> : null}

            <Layout
              style={{
                justifyContent: 'flex-end',
                flexDirection: 'row',
                marginVertical: 10,
              }}>
              <Button
                style={styles.cancelButton}
                onPress={() => this.props.navigation.goBack()}>
                Cancel
            </Button>

              <Button
                style={styles.submitButton}
              // type="submit"
              // disabled={!isValid || this.state.formSpinner}
              >
                {isValid + ' Submit'}
              </Button>
            </Layout>
          </Layout>
        </ScrollView>)}
      </Formik>
    );
  }
}

const styles = StyleSheet.create({
  submitButton: {
    borderColor: '#00c851',
    backgroundColor: '#00c851',
    marginStart: 5,
  },
  cancelButton: {
    borderColor: '#ff3547',
    backgroundColor: '#ff3547',
  },
  labelColor: {
    color: '#8F9BB3',
  },
  centeredContentViewStyle: {
    justifyContent: 'center',
    alignItems: "center",
    padding: 2,
    marginVertical: 5
  },
  errorMessageStyle: {
    color: 'red'
  }
});

【问题讨论】:

    标签: javascript react-native formik yup react-native-ui-kitten


    【解决方案1】:

    我使用 Formik 和 Chakra UICheckbox 并最终使用 onChange 事件来解决这个问题,如下所示:

    <Field name="terms">
      {({ field }) => (
        <Checkbox
          id="terms"
          name="terms"
          onChange={(e) => setFieldValue('terms', e.target.checked)}
        >
          <Text fontSize="sm" textAlign="left">
            I agree to the Terms and Conditions.
          </Text>
        </Checkbox>
      )}
    </Field>
    

    我相信与 UI Kitten 的工作类似。

    GitHub comment 对 Yup 验证非常有帮助。

    【讨论】:

      【解决方案2】:

      Formik 期望接收 ChangeEvent 作为handleChange 函数的参数。您可以使用Input 来实现,但不能使用RadioCheckBox,因为简而言之,这些组件通过处理来自TouchableOpacity 的常规onPress 来模拟此事件。

      我的解决方案是使用钩子来处理这些更改,然后将状态与来自 Formik 的结果对象结合起来。

      【讨论】:

      • 不过,你可以使用(checked) =&gt; formik.setFieldValue('valueName', checked)
      • 如果您看到我的代码有问题,我已经实现了它,实际上提到的解决方案适用于复选框,现在我正在尝试使 formikUI Kitten Radio Buttons 一起使用。感谢您的回复。
      • 你有没有偶然发现这个问题?遇到同样的问题
      【解决方案3】:

      我正在使用 material-ui,但我相信解决方案可以类似。如果您在将 formik 与任何库链接时遇到问题,请尝试公开表单/字段 api 并手动设置属性。当它起作用时,尝试删除一些由 formik 自动处理的属性以避免重新创建轮子。

      这就是我实现 radiogroup 的方式:

      <Field name="fieldName" value={formik.values.fieldName}>
        {({ form }) => (
          {/* Fragment is used here, to make possible to add a FormHelperText under Field. */}
          <React.Fragment>
            {/* Remember to use same name as in the parent Field. form.handleEvent will make it work when you click on one of the options. */}
            <RadioGroup name="fieldName" onChange={form.handleChange}>
              <FormControlLabel value="A" control={<Radio />} label="Value A" />
              <FormControlLabel value="B" control={<Radio />} label="Value B" />
              <FormControlLabel value="C" control={<Radio />} label="Value C" />
            </RadioGroup>
            <FormHelperText error={Boolean(form.errors.fieldName) && form.touched.fieldName}>
              {form.errors.fieldName}
            </FormHelperText>
          </React.Fragment>
        )}
      </Field>
      

      参考资料:

      【讨论】:

        【解决方案4】:

        Uı 套件或元素无关紧要。您可以轻松地使用 formik 和 yup。

        • 添加初始值
        • 将您的单选元素添加到您的验证架构中,并将您的要求设置为必需。
        • 使用 setFieldValue 或操作值
        • 然后繁荣!

        【讨论】:

          猜你喜欢
          • 2021-10-28
          • 2019-10-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-09
          • 2015-10-31
          相关资源
          最近更新 更多