如果我有一个功能组件并且想要在 Formik 标签之外设置一个值,我该怎么做?下面是我需要进一步说明的代码。
function XYZScreen() {
const someFunctionWithLogic = () => {
// Set the value of the number field here...
}
return (
<Screen>
<Formik>
<FormField name="number" placeholder="Number" />
</Formik>
</Screen>
);
}
我已将代码减少到尽可能少,以简化问题。这个问题在问题的上下文中可能没有意义,但我认为我的要求很清楚。
如果您需要更多代码,请告诉我,如果需要,我很乐意提供。
useFormik
钩子代替:
import { useFormik } from 'Formik'
function XYZScreen() {
const formikProps = useFormik({
initialValues,
validationSchema,
onSubmit: yourSubmitFunction,
...etc
})
const someFunctionWithLogic = () => {
// Set the value of the number field here:
formikProps.setFieldValue("number", someNumber)
}
return (
<Screen>
{/* No need for Formik component */}
<FormField
name="number"
placeholder="Number"
value={formikProps.values.number} // or whatever the value is
onChange={formikProps.handleChange}
/>
</Screen>
);
}
因此,您基本上是在函数体内设置所有表单道具,并且可以在那里访问它们。 Formik 有很多很棒的辅助钩子和函数,我强烈建议梳理文档。
如果您真的喜欢
Formik
标签,您可以继续使用它。只需创建一个 Formik
包装器组件,并使用 useFormikContext
: 在后代中使用自定义逻辑
// FormWrapper.js
const FormWrapper = () => (
<Formik
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={yourOnSubmitFunction}
>
<SomeChild />
</Formik>
)
// SomeChild.js
const SomeChild = () => {
// returns all values and methods from your Formik tag
const formikProps = useFormikContext()
const someFunctionWithLogic = () => {
formikProps.setFieldValue("number", someNumber)
}
return (
<Screen>
<FormField
name="number"
placeholder="Number"
value={formikProps.values.number} // or whatever the value is
onChange={formikProps.handleChange}
/>
</Screen>
);
}
实现此目的的最佳方法是将 setFieldValue 函数传递给您想要的函数,因此代码应如下所示
function XYZScreen() {
const someFunctionWithLogic = (value, setFieldValue) => {
// Set the value of the number field here...
setFieldValue('price', value)
}
return (
<Screen>
<Formik>
<FormField name="number" placeholder="Number" onChange={(e) => { handleChange(e); someFunctionWithLogic(value, setFieldValue ); }} />
</Formik>
</Screen>
);
}
参考https://web-brackets.com/discussion/12/how-to-use-setfieldvalue-from-outside-render-function-formik
我自己也遇到了类似的问题,并根据 Seth Lutske 的评论提出了另一个解决方案。您可以将使用
useFormik
与手动创建 Formik 上下文结合起来。 useFormik
非常强大,但它的缺点是它不会创建上下文,因此你不能在子组件中使用useField
或useFormikContext
,并且需要手动传递所有相关的props(value,onChange,onBlur)等)。
您可以做的是使用
useFormik
创建 Formik 上下文对象,并使用 <FormikProvider>
手动向下传递上下文。通过这种方法,您可以继续使用所有字段,就像它们被包裹在 <Formik>
中一样
import { useFormik, FormikProvider } from 'formik'
function XYZScreen() {
const formikProps = useFormik({
initialValues,
validationSchema,
onSubmit: yourSubmitFunction,
...etc
})
const someFunctionWithLogic = () => {
// Set the value of the number field here:
formikProps.setFieldValue("number", someNumber)
}
return (
<Screen>
{/* FormikProvider component instead of Formik */}
<FormikProvider value={formikProps}>
<FormField
name="number"
placeholder="Number"
/>
</FormikProvider>
</Screen>
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
您也可以使用
initialValues
轻松完成此操作
<Formik
initialValues={{
"fieldName": this.state.value,
}}
enableReinitialize
...
>
...
</Formik>
同样对于功能组件,您可以使用
useEffect
内的 Formik
来完成此操作,使用 const [value,setValue] = useState()
设置值
<Formik
initialValues={{}}
onSubmit={(values, { resetForm }) => _submit(values, resetForm)}
validationSchema={buildValidationSchema(actionItem.fields)}
>
{({ setFieldValue, handleSubmit, values, errors, touched }) => {
useEffect(() => {
setFieldValue("fieldName",value);
}, [value]);
...
</Formik>
为什么不尝试使用
initialProps
重置表单?
function XYZScreen() {
const [number, setNumber] = useState()
const someFunctionWithLogic = () => {
// Set the value of the number field here...
setNumber(...)
}
return (
<Screen>
<Formik initialProps={{number}}>
<FormField name="number" placeholder="Number" />
</Formik>
</Screen>
);
}
另一个建议是将该数字传递给 Formik 的内部组件:
function SomeChild(props) {
const {number, setFieldValue} = props;
useEffect(() => {
setFieldValue('number', number);
}, [number]);
return (
<FormField name="number" placeholder="Number" />
)
}
function XYZScreen() {
const [number, setNumber] = useState()
const someFunctionWithLogic = () => {
// Set the value of the number field here...
setNumber(...)
}
return (
<Screen>
<Formik>
{(props) => <SomeChild number={number} {...props} />
</Formik>
</Screen>
);
}