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

React中useReducer实现多密码框独立显隐的问题及修复

问题分析与修复方案

问题根源

你的代码核心问题在于用单一全局状态控制两个独立的密码输入框:

  • 全局只维护了一组inputType和isShowPassword状态,没有区分“创建密码”和“确认密码”的独立状态
  • 两个输入框都绑定同一个inputType,任何一个切换按钮触发的action都会修改这组全局值,导致两个输入框同步显示/隐藏

修复方案

我们需要拆分状态,给每个密码输入框分配独立的状态,并让reducer能够精准修改对应输入框的状态。

步骤1:重构状态结构

把默认状态拆分为两个独立的字段,分别对应两个密码输入框:

// 单个密码输入框的状态类型
type PasswordFieldState = {
  inputType: string;
  isShowPassword: boolean;
};

// 全局状态类型
type StateType = {
  createPassword: PasswordFieldState;
  confirmPassword: PasswordFieldState;
};

// 初始状态
const defaultState: StateType = {
  createPassword: {
    inputType: "password",
    isShowPassword: false,
  },
  confirmPassword: {
    inputType: "password",
    isShowPassword: false,
  },
};

步骤2:更新Action类型

让action携带目标字段标识,告诉reducer要修改哪个输入框的状态:

type ActionTypes = {
  type: "SHOW" | "HIDE";
  payload: {
    field: "createPassword" | "confirmPassword";
  };
};

步骤3:重写Reducer逻辑

根据action中的field标识,只更新对应输入框的状态,不影响另一个:

const reducerFunction = (state: StateType, action: ActionTypes) => {
  const { field } = action.payload;
  switch (action.type) {
    case "SHOW":
      return {
        ...state,
        [field]: {
          ...state[field],
          inputType: "text",
          isShowPassword: true,
        },
      };
    case "HIDE":
      return {
        ...state,
        [field]: {
          ...state[field],
          inputType: "password",
          isShowPassword: false,
        },
      };
    default:
      return state;
  }
};

步骤4:更新组件状态传递与使用

在父组件传递拆分后的状态,子组件分别绑定对应输入框的状态:

const Login = () => {
  const [state, dispatch] = useReducer(reducerFunction, defaultState);
  const [isAlreadyMember, setIsAlreadyMember] = useState(true);

  return (
    <section>
      <div>
        <Signup
          dispatch={dispatch}
          createPasswordState={state.createPassword}
          confirmPasswordState={state.confirmPassword}
          setIsAlreadyMember={setIsAlreadyMember}
        />
      </div>
    </section>
  );
};

// 更新Signup组件的Props类型
type SignupProps = {
  dispatch: Dispatch<ActionTypes>;
  createPasswordState: PasswordFieldState;
  confirmPasswordState: PasswordFieldState;
  setIsAlreadyMember: React.Dispatch<React.SetStateAction<boolean>>;
};

const Signup = ({
  dispatch,
  createPasswordState,
  confirmPasswordState,
  setIsAlreadyMember,
}: SignupProps) => {
  return (
    <div>
      <form action="">
        <input type="email" name="email" placeholder="email" />
        {/* 创建密码输入框 */}
        <div>
          <input
            type={createPasswordState.inputType}
            name="password"
            placeholder="create password"
          />
          {!createPasswordState.isShowPassword ? (
            <button
              onClick={(e) => {
                e.preventDefault();
                dispatch({
                  type: "SHOW",
                  payload: { field: "createPassword" },
                });
              }}
              className="bg-none text-xs  absolute right-0 p-3 bottom-0"
            >
              Show
            </button>
          ) : (
            <button
              onClick={(e) => {
                e.preventDefault();
                dispatch({
                  type: "HIDE",
                  payload: { field: "createPassword" },
                });
              }}
            >
              Hide
            </button>
          )}
        </div>
        {/* 确认密码输入框 */}
        <div>
          <input
            type={confirmPasswordState.inputType}
            name="password"
            placeholder="reenter password"
          />
          {!confirmPasswordState.isShowPassword ? (
            <button
              onClick={(e) => {
                e.preventDefault();
                dispatch({
                  type: "SHOW",
                  payload: { field: "confirmPassword" },
                });
              }}
            >
              Show
            </button>
          ) : (
            <button
              onClick={(e) => {
                e.preventDefault();
                dispatch({
                  type: "HIDE",
                  payload: { field: "confirmPassword" },
                });
              }}
            >
              Hide
            </button>
          )}
        </div>
        <button
          onClick={(e) => e.preventDefault()}
          className="primary-btn w-full mt-5"
        >
          Sign Up
        </button>
      </form>
    </div>
  );
};

关键改动说明

  • 状态拆分:将单一全局状态拆分为两个独立的状态对象,各自维护自己的显隐状态
  • Action精准定位:每个切换操作都明确指定要修改的输入框,避免全局覆盖
  • Reducer局部更新:只修改目标输入框的状态,不影响另一个输入框的原有状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 17:30:59