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

使用React Context API无法修改表单输入框值的问题求助

React Context API 输入框无法修改的问题解决

你的问题核心在于reducer中直接修改了原state对象,违反了React状态不可变的原则,导致组件无法感知状态变化,所以输入框值始终不会更新。

问题代码分析

在myComponentDataReducer中,你直接修改了原state的属性:

const myComponentDataReducer = (state, action) => {
    if (action.type === "UPDATE_INPUT_1") {
        state.data.input_1 = action.val // 直接修改原state,不会触发组件重新渲染
    }
    return state
}

React依赖状态的引用变化来判断是否需要重新渲染组件。直接修改原对象的属性不会改变state的引用,因此组件无法检测到状态更新,输入框始终显示初始值。

解决方案:实现不可变状态更新

修改reducer,返回一个全新的状态对象,逐层拷贝原对象的属性,确保每一层的引用都是新的:

const myComponentDataReducer = (state, action) => {
    if (action.type === "UPDATE_INPUT_1") {
        return {
            ...state, // 拷贝外层state对象
            data: {
                ...state.data, // 拷贝内层data对象
                input_1: action.val // 更新目标属性
            }
        }
    }
    return state
}

这样每次更新状态时,都会生成新的状态对象,React能检测到引用变化,触发组件重新渲染,输入框的值就会同步更新了。

完整修改后的代码

import React from 'react';
import * as ReactDOM from "react-dom/client";

const defaultComponentState = {
    data: {
        input_1: 123,
    }
}

const componentStateFuncs = {
    funcs: {
        updateInput1: (val) => {},
    }
}
const MyComponentDataContext = React.createContext({...defaultComponentState,...componentStateFuncs})

// 修改后的reducer
const myComponentDataReducer = (state, action) => {
    if (action.type === "UPDATE_INPUT_1") {
        return {
            ...state,
            data: {
                ...state.data,
                input_1: action.val
            }
        }
    }
    return state
}

const MyComponentDataProvider = (props) => {
    let [componentState, dispatchComponentAction] = React.useReducer(myComponentDataReducer, defaultComponentState)

    const updateInput1Value = (val) => {
        dispatchComponentAction({type: "UPDATE_INPUT_1", val: val})
    }
    const componentContext = {
        funcs: {
            updateInput1: updateInput1Value,
        },
        data: {
            input_1: componentState.data.input_1,
        }
    }
    console.log(`State in MyComponentDataProvider: ${JSON.stringify(componentState)}`)
    return (
        <MyComponentDataContext.Provider value={componentContext}>
            {props.children}
        </MyComponentDataContext.Provider>
    )
}

const MyComponent = (props) => {
    const myComponentCtx = React.useContext(MyComponentDataContext);

    const input1Handler = (event) => {
        myComponentCtx.funcs.updateInput1(event.target.value);
    }

    const submitForm = (event) => {
        props.onSubmitSearch(myComponentCtx.data)
    }

    return (
        <div id="my_component">
            <form onSubmit={submitForm}>
                <div>
                    <label htmlFor="input_1">Input 1</label><br/>
                    <input name="input_1" type="number" onChange={input1Handler} value={myComponentCtx.data.input_1}></input>
                </div>
                <div>
                    <button id="myComponentSubmit" className="btn btn-outline-light" type="submit">Submit</button>
                </div>
            </form>
        </div>
    )
}

const App = () => {
    const handleSubmitForm = async (params) => {
        console.log(`State in handleSubmitForm: ${JSON.stringify(params)}`)
    };

    return (
        <div id="app-container">
            <MyComponentDataProvider>
                <div id="mycomponent-container">
                    <MyComponent 
                        onSubmitSearch={handleSubmitForm}>
                    </MyComponent>
                </div>
            </MyComponentDataProvider>
        </div>
    );
}

const container = document.getElementById('app');
const root = ReactDOM.createRoot(container);
root.render(<App  />);

额外说明

  • 对于嵌套结构的状态,必须逐层浅拷贝,确保每一层的引用都是新的,React才能正确识别状态变化。
  • 你的Context绑定逻辑本身是正确的,只要状态更新符合不可变原则,输入框就能正常响应用户输入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 11:07:22