You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中Formik onChange不触发及跨组件表单值同步问题

问题解决方案

问题1:输入框onChange无输出、initVal.q4不更新的修复

  • 自定义onChange被覆盖:你在Input中先声明了自定义onChange,随后用{...field}引入Formik的field对象,而field自带的onChange会覆盖你的自定义逻辑,导致控制台无输出。要保留自定义行为,需将两者结合执行。
  • initVal非响应式状态:initVal是普通变量,组件重新渲染时会被重新初始化,无法追踪输入框的内容变化。需要用React的useState来管理q4的值,确保响应式更新。

修复后的Input代码:

<Input 
  borderRadius={0}
  id="q4"
  h="50px"
  p="1"
  {...field} 
  onChange={(e) => {
    // 先执行Formik的onChange更新表单状态
    field.onChange(e);
    // 再执行自定义打印逻辑
    console.log(e.target.value);
  }}
  placeholder="Please input your answer"/>

改造Part4的状态管理:

import React, { useState } from 'react';
import {
  Box,
  Input,
  Text,
  Flex,
  Button,
  Heading,
  Grid,
  GridItem,
} from '@chakra-ui/react';
import { Field, Formik, Form } from 'formik';
import KPIForm from '../KPIForm';
import ButtonGroup from '../ButtonGroup';

export default function Part4({ values, setPage}) {
  // 用useState管理q4的值,初始化时从props.values读取
  const [q4Value, setQ4Value] = useState(values ? values.q4.answers[0] : '');
  
  const initVal = {
    q4: q4Value,
    q5: {
      a1: ['', { value: 0, unit: '%' }, { value: 0, unit: '%' }, { value: 0, unit: '%' }, { value: 0, unit: '%' }],
      a2: ['', { value: 0, unit: '($)' }, { value: 0, unit: '($)' }, { value: 0, unit: '($)' }, { value: 0, unit: '($)' }],
    }
  };
 
  if(values){
    const { q5 } = values;
    initVal.q5 = q5.answers;
    initVal.q5.a1 = q5.answers.a1;
    initVal.q5.a2 = q5.answers.a2;
  }

  return (
    <>
      <Box bg={'white'} p="4">
        <Formik
          enableReinitialize
          initialValues={{q4: q4Value}}
          // 监听Formik值变化,同步更新外部state
          onValuesChange={(newValues) => setQ4Value(newValues.q4)}
        >
          {(props) => (
            <Form>
              <Heading as="h3" size={'sm'} paddingBottom="5">
                4. Of all your PERSONAL priorities, what do you want to achieve most in the next 90 days?
              </Heading>
              <Box mb={10}>
                <Field name="q4" type="text">
                  {({field, form, meta}) => (
                    <Input 
                      borderRadius={0}
                      id="q4"
                      h="50px"
                      p="1"
                      {...field} 
                      onChange={(e)=>{
                        field.onChange(e);
                        console.log(e.target.value);
                      }}
                      placeholder="Please input your answer"/>
                  )}
                </Field>
              </Box>
              <br/>
              <Heading as="h3" size={'sm'} paddingBottom="5">
                5. Now think about how to measure this. What is the best result you think deserves a reward remembering, anything greater than 80% should be rewarded.
              </Heading>
            </Form>
          )}
        </Formik>
        {/* 传递包含最新q4的initValues给KPIForm */}
        <KPIForm initValues={{...initVal, q4: q4Value}} pageNo={4} setPage={setPage}/>
      </Box>
    </>
  );
}

问题2:让KPIForm实时获取q4更新值

通过上述改造,q4Value会实时同步Formik中q4的输入值,传递给KPIForm后,只需在KPIForm中监听initValues的变化即可拿到最新q4:

KPIForm中监听更新:

export default function KPIForm({ initValues, pageNo, setPage }) {
    const { contextValue, setProgress, updateSection, setSection } = 
        useContext(SectionsContext);
    const {
        quickStart,
        rewardsCelebrations,
        strengthsOpportunities,
        visionOfSuccess,
        numbers,
    } = contextValue;
    const progress = rewardsCelebrations.progress;

    let initVal = pageNo == 2 ? initValues : initValues.q5;
    
    useEffect(()=>{
        console.log('最新的q4值:', initValues.q4);
        // 在这里处理q4更新后的逻辑
    }, [initValues])

    return (
        <>
            <Box>
      ........
    </>
  );
}

更简洁的方式:单独传递q4 props

如果不需要传递整个initValues,可以直接把q4作为单独props传入,监听更精准:

// Part4中传递
<KPIForm q4={q4Value} initValues={initVal} pageNo={4} setPage={setPage}/>

// KPIForm中接收并监听
export default function KPIForm({ q4, initValues, pageNo, setPage }) {
    const { contextValue, setProgress, updateSection, setSection } = 
        useContext(SectionsContext);
    const {
        quickStart,
        rewardsCelebrations,
        strengthsOpportunities,
        visionOfSuccess,
        numbers,
    } = contextValue;
    const progress = rewardsCelebrations.progress;

    let initVal = pageNo == 2 ? initValues : initValues.q5;
    
    useEffect(()=>{
        console.log('最新的q4值:', q4);
        // 后续处理逻辑
    }, [q4])

    return (
        <>
            <Box>
      ........
    </>
  );
}

内容的提问来源于stack exchange,提问作者Shotto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 21:57:32