首页 > 解决方案 > 如何使用 Header / navigationOptions 中的 formik 并触发 handleSubmit onpress HeaderRight

问题描述

目标

将参数传递给导航以便访问

onPress={props.handleSubmit}

在一个简单的 React Natie 应用程序中,在里面#EditProductScreen.js

我有这个模式

//import
import React, { useState, useEffect, useCallback } from 'react';
...
import { Formik, ErrorMessage } from 'formik';
import * as Yup from 'yup';
...

//compnt
const EditProductScreen = props => {
...
}

//Navigation
EditProductScreen.navigationOptions = navData => {
...
};

//Style
const styles = StyleSheet.create({
  form: {
    margin: 20
  },
...
});

export default EditProductScreen;

我看到了这些问题和答案,但不幸的是无法找出我需要的正确方法在这里问题 和这里回答jaredpalmer

此链接也可能非常接近目标模式 ,但是该示例中没有添加任何导航选项

我有一个严重的问题(因为无法使用 formik 计算 NavigationOption 设置)使用您在此处提供的技巧 一个解释目标的屏幕截图 在此处输入图像描述

潜入主 cmpnt 和导航

#cpnt

const EditProductScreen = props => {
   //some code 
   ...

  return (
    <ScrollView>
      <Formik
        initialValues={{ title: title, email: '' }}
        validationSchema={Yup.object({
          title: Yup.string()
            .min(2, 'Too Short!')
            .max(50, 'Too Long!')
            .required('Required')
        })}
        onSubmit={(values, formikActions) => {
          submitHandler();
        }}
      >
        {props => (
          <View>
            <View style={styles.form}>
              <View style={styles.formControl}>
                <Text style={styles.label}>Title</Text>
                <TextInput
                  // some code
                />

              // some code

              </View>
            </View>
            <Button
              title={'submit'}
              onPress={props.handleSubmit}
              color='black'
              mode='contained'
              loading={props.isSubmitting}
              disabled={props.isSubmitting}
              style={{ marginTop: 16 }}
            >
              Submit
            </Button>
          </View>
        )}
      </Formik>
    </ScrollView>
  );
};

#navigation

EditProductScreen.navigationOptions = navData => {
  const submitFn = navData.navigation.getParam('submit');
  return {
    headerTitle: navData.navigation.getParam('productId')
      ? 'Edit Product'
      : 'Add Product',
    headerRight: (
      <HeaderButtons HeaderButtonComponent={HeaderButton}>
        <Item
          title='Save'
          iconName={
            Platform.OS === 'android' ? 'md-checkmark' : 'ios-checkmark'
          }
          onPress={submitFn}
          // here the challenge 

        />
      </HeaderButtons>
    )
  };
};

所以我在这里,我试着在里面建造这样的东西

我猜什么

创建一个使用效果

 useEffect(() => {
        navigation.setParams({ handleSubmit: handleSubmit.bind() });
    }, []);

并从导航中调用它......但是如何在这个 useEffect 中调用 handleSubmit 呢?之前如何认真定义handleSubmit,以便在useEffect中使用它?

假设我成功构建了那个 useEffect

然后从导航中调用它

EditProductScreen.navigationOptions = navData => {
const submitForValidation = navData.navigation.getParam('handleSubmit');
// some code 
    headerRight: (
      <HeaderButtons HeaderButtonComponent={HeaderButton}>
        <Item
          // some code 
          onPress={submitForValidation}
        />
      </HeaderButtons>
    )
}

如果有帮助,我会为我当前的代码做点零食。 小吃

标签: react-nativeformik

解决方案


您需要使用 HOC 并使用 withFormik 包装您的表单。

这是一个例子

const sendDataToAPI = (values,options) => {
  //save data 
}

const formWrapper = withFormik({
  enableReinitialize: true,
  mapPropsToValues: props => ({}),
  validationSchema: yup.object().shape({
    title: yup.string().required("field is required"),
    
  }),
  validate: (values, props) => {
    let errors = {}
    return errors
  },
  handleSubmit: (values,actions) => {
  	sendDataToAPI(values,actions)
  },
})


const form = props => {
  const {
    values,
    actions,
    handleSubmit,
    setFieldValue,
    navigation,
    status
  } = props;
  
  React.useEffect(() => { 
      navigation.setParams({ 
          saveForm: handleSubmit
      }) 
  }, [])

  return (
  	<SafeAreaView>
	  	<View >
	  	    {status && status.hasOwnProperty('errors') && (
	            <View>
	                <Text>{status.errors}</Text>
	            </View>
	        )}
	  	    <View>
	  	        <Text>Title</Text>
	  	        <Field component={FKTextInput} name="title" />
	  	    </View>
	  	</View>

	 </SafeAreaView>
  )
}
form.navigationOptions = ({ navigation }) => {
	return {
		headerLeft: (
            <View>
            <TouchableOpacity onPress={() => navigation.goBack()}>
            	<Text>Cancel</Text>
            </TouchableOpacity>
            </View>
        ),
        headerRight: (
            <View>
            <TouchableOpacity onPress={() => {navigation.state.params.saveForm()}}>
                <Text>Save</Text>
            </TouchableOpacity>
            </View>
        ),
       
        title: 'Save product'
	}
}

export default formWrapper(form)


推荐阅读