如何使用Header / navigationOptions和触发器句柄中的formik提交onpress HeaderRight

时间:2019-09-19 19:35:51

标签: react-native formik

目标

将参数传递给导航以访问

onPress={props.handleSubmit}

在一个简单的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;

我看到了这些问题并回答了,但不幸的是找不到正确的方法来满足我的需求 这里的issue 然后在这里回答jaredpalmer

此链接也可能非常接近the targeted pattern 但是,没有向该示例添加navigationOptions

我遇到了一个严重的问题(因为无法通过formik来确定NavigationOption的设置)以使用您在此处提供的技巧 这是说明目标的屏幕截图 enter image description here

潜入主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

 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>
    )
}

如果对当前代码有帮助,我会做一些零食。 Snack

2 个答案:

答案 0 :(得分:0)

我曾经遇到过同样的问题,并提出以下解决方法。

首先,删除此行

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

第二,设置对Formik子代渲染的标头的引用

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 => {

                // ***************************************
                // ADDED THIS LINE TO PASS PARAM TO HEADER
                // ***************************************
                navigation.setParams({ handleSubmit: props.handleSubmit });

                return (
                    <View>
                        <View style={styles.form}>
                            <View style={styles.formControl}>
                                <Text style={styles.label}>Title</Text>
                                <TextInput
   ..... the rest

我认为可能还有其他更好的解决方案,例如通过Formik的裁判,或者您需要了解更多信息

答案 1 :(得分:0)

您需要使用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)