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

React中多组Yes/No按钮的状态管理优化方案咨询

优化多组Yes/No选项的React组件代码

问题背景

我开发了一个包含多组Yes/No选项的React组件,需求为:点击Yes按钮时该按钮背景变为绿色、No按钮变为红色;点击No按钮时该按钮背景变为绿色、Yes按钮变为红色。但目前为每组按钮单独创建了state,这并非最佳实践,希望得到更优的处理方式。

原代码

import React, { useState } from "react";
import "./Medicine.css";

const Medicine = () => {
  const [selectedButton, setSelectedButton] = useState("");
  const [selectedButton1, setSelectedButton1] = useState("");
  const [selectedButton2, setSelectedButton2] = useState("");
  const [selectedButton3, setSelectedButton3] = useState("");
  const [selectedButton4, setSelectedButton4] = useState("");
  const [selectedButton5, setSelectedButton5] = useState("");
  return (
    <>
      <h1>Medicine</h1>
      <div className="parent_div">
        <div className="child_div">
          <p>page2</p>
          <div className="grand_div">
            <div className="fcontainer">
              <div className="fitem">
                Did You come into the pharmacy today for Medicine?
              </div>
              <div className="fitem">
                <button
                  className={
                    selectedButton !== ""
                      ? selectedButton === "no"
                        ? "butn greenbtn"
                        : "butn redbtn"
                      : "butn"
                  }
                  onClick={() => setSelectedButton("no")}
                >
                  No
                </button>
                <button
                  className={
                    selectedButton !== ""
                      ? selectedButton === "yes"
                        ? "butn greenbtn"
                        : "butn redbtn"
                      : "butn"
                  }
                  onClick={() => setSelectedButton("yes")}
                >
                  Yes
                </button>
              </div>
            </div>

            <hr />
            <div>
              <h5>Where do you asked any of the following:</h5>
              <div style={{ marginTop: "10px" }}>
                <div className="fcontainer">
                  <div className="fitem ques">Who is the Medicine for?</div>
                  <div className="fitem ">
                    <button
                      className={
                        selectedButton1 !== ""
                          ? selectedButton1 === "no"
                            ? "butn greenbtn"
                            : "butn redbtn"
                          : "butn"
                      }
                      onClick={() => setSelectedButton1("no")}
                    >
                      No
                    </button>
                    <button
                      className={
                        selectedButton1 !== ""
                          ? selectedButton1 === "yes"
                            ? "butn greenbtn"
                            : "butn redbtn"
                          : "butn"
                      }
                      onClick={() => setSelectedButton1("yes")}
                    >
                      Yes
                    </button>
                  </div>
                </div>
                <div className="fcontainer">
                  <div className="fitem ques">What are yours symptoms?</div>
                  <div className="fitem">
                    <button
                      className={
                        selectedButton2 !== ""
                          ? selectedButton2 === "no"
                            ? "butn greenbtn"
                            : "butn redbtn"
                          : "butn"
                      }
                      onClick={() => setSelectedButton2("no")}
                    >
                      No
                    </button>
                    <button
                      className={
                        selectedButton2 !== ""
                          ? selectedButton2 === "yes"
                            ? "butn greenbtn"
                            : "butn redbtn"
                          : "butn"
                      }
                      onClick={() => setSelectedButton2("yes")}
                    >
                      Yes
                    </button>
                  </div>
                </div>
                <div className="fcontainer">
                  <div className="fitem ques">
                    How long you had the symptoms?
                  </div>
                  <div className="fitem">
                    <button
                      className={
                        selectedButton3 !== ""
                          ? selectedButton3 === "no"
                            ? "butn greenbtn"
                            : "butn redbtn"
                          : "butn"
                      }
                      onClick={() => setSelectedButton3("no")}
                    >
                      No
                    </button>
                    <button
                      className={
                        selectedButton3 !== ""
                          ? selectedButton3 === "yes"
                            ? "butn greenbtn"
                            : "butn redbtn"
                          : "butn"
                      }
                      onClick={() => setSelectedButton3("yes")}
                    >
                      Yes
                    </button>
                  </div>
                </div>
                <div className="fcontainer">
                  <div className="fitem ques">
                    What action have you already taken?
                  </div>
                  <div className="fitem">
                    <button
                      className={
                        selectedButton4 !== ""
                          ? selectedButton4 === "no"
                            ? "butn greenbtn"
                            : "butn redbtn"
                          : "butn"
                      }
                      onClick={() => setSelectedButton4("no")}
                    >
                      No
                    </button>
                    <button
                      className={
                        selectedButton4 !== ""
                          ? selectedButton4 === "yes"
                            ? "butn greenbtn"
                            : "butn redbtn"
                          : "butn"
                      }
                      onClick={() => setSelectedButton4("yes")}
                    >
                      Yes
                    </button>
                  </div>
                </div>
                <div className="fcontainer">
                  <div className="fitem ques">
                    Are you taking any other medication?
                  </div>
                  <div className="fitem">
                    <button
                      className={
                        selectedButton5 !== ""
                          ? selectedButton5 === "no"
                            ? "butn greenbtn"
                            : "butn redbtn"
                          : "butn"
                      }
                      onClick={() => setSelectedButton5("no")}
                    >
                      No
                    </button>
                    <button
                      className={
                        selectedButton5 !== ""
                          ? selectedButton5 === "yes"
                            ? "butn greenbtn"
                            : "butn redbtn"
                          : "butn"
                      }
                      onClick={() => setSelectedButton5("yes")}
                    >
                      Yes
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </>
  );
};

export default Medicine;

优化方案

1. 合并状态管理

将多个独立的useState合并为一个对象状态,用问题标识作为键,选中值作为值,简化状态维护。

2. 提取复用组件

创建YesNoButtonGroup组件,封装按钮的样式逻辑和点击事件,避免重复代码。

3. 数据驱动渲染

把所有问题整理成数组,通过遍历数组生成对应的选项组,新增问题只需修改数据数组即可。

优化后的完整代码

第一步:创建复用的按钮组件

// YesNoButtonGroup.js
import React from "react";

const YesNoButtonGroup = ({ questionId, selectedValue, onSelect }) => {
  const getButtonClass = (buttonType) => {
    if (!selectedValue) return "butn";
    return selectedValue === buttonType ? "butn greenbtn" : "butn redbtn";
  };

  return (
    <div className="fitem">
      <button
        className={getButtonClass("no")}
        onClick={() => onSelect(questionId, "no")}
      >
        No
      </button>
      <button
        className={getButtonClass("yes")}
        onClick={() => onSelect(questionId, "yes")}
      >
        Yes
      </button>
    </div>
  );
};

export default YesNoButtonGroup;

第二步:重构Medicine组件

import React, { useState } from "react";
import "./Medicine.css";
import YesNoButtonGroup from "./YesNoButtonGroup";

const Medicine = () => {
  // 用单个对象管理所有选项的选中状态
  const [selectedAnswers, setSelectedAnswers] = useState({});

  // 统一的选择处理函数
  const handleSelect = (questionId, value) => {
    setSelectedAnswers(prev => ({
      ...prev,
      [questionId]: value
    }));
  };

  // 定义所有问题数据
  const mainQuestion = {
    id: "main",
    text: "Did You come into the pharmacy today for Medicine?"
  };

  const subQuestions = [
    { id: "forWho", text: "Who is the Medicine for?" },
    { id: "symptoms", text: "What are your symptoms?" },
    { id: "symptomDuration", text: "How long have you had the symptoms?" },
    { id: "takenAction", text: "What action have you already taken?" },
    { id: "otherMedication", text: "Are you taking any other medication?" }
  ];

  return (
    <>
      <h1>Medicine</h1>
      <div className="parent_div">
        <div className="child_div">
          <p>page2</p>
          <div className="grand_div">
            {/* 主问题 */}
            <div className="fcontainer">
              <div className="fitem">{mainQuestion.text}</div>
              <YesNoButtonGroup
                questionId={mainQuestion.id}
                selectedValue={selectedAnswers[mainQuestion.id]}
                onSelect={handleSelect}
              />
            </div>

            <hr />
            <div>
              <h5>Were you asked any of the following:</h5>
              <div style={{ marginTop: "10px" }}>
                {/* 子问题列表,通过循环渲染 */}
                {subQuestions.map(question => (
                  <div key={question.id} className="fcontainer">
                    <div className="fitem ques">{question.text}</div>
                    <YesNoButtonGroup
                      questionId={question.id}
                      selectedValue={selectedAnswers[question.id]}
                      onSelect={handleSelect}
                    />
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>
      </div>
    </>
  );
};

export default Medicine;

优化说明

  • 状态管理更高效:单个对象状态替代多个独立state,便于统一维护和后续扩展(比如批量获取所有答案)。
  • 代码复用性提升:YesNoButtonGroup组件封装了按钮的样式逻辑和交互逻辑,避免了大量重复的JSX和样式判断代码。
  • 数据驱动更灵活:问题数据抽离成数组后,新增或修改问题只需调整数据数组,无需修改渲染逻辑,降低维护成本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 04:02:57