【问题标题】:How to implement a check all button for radio buttons, using React Hooks?如何使用 React Hooks 实现单选按钮的检查所有按钮?
【发布时间】:2020-12-04 15:36:38
【问题描述】:

不要对检查页面上的每个单选按钮感到困惑。我想实现一个check all button,它将嵌套对象状态的值设置为某个值。我以嵌套状态存储每个问题。例如。

formQuestions({ 
  kitchen: [question,question2,question3],
  living: [question,question2,question3]
})

为每个问题制作了四个单选按钮。现在一次只能选择一个单选按钮。每个单选按钮都有自己的值。前任。 `“好”、“一般”、“差”、“不适用”。

选择单选按钮时,为该部分和问题动态生成状态。例如。

formAnswers({
  kitchen: {
    question: "Good"
    question2: "Poor"
  }
})

这里的目标是我要创建的按钮,它只检查每个问题的一个值,例如。 点击按钮 question: "Good", question2: "Good" etc..

要设置动态值的状态,我需要“部分名称”,我们将其称为Name,将“问题”称为question。这样我就可以像formAnswers[Name][question]: value

那样访问值

我正在尝试从名为SectionHeader 的组件中设置该状态。这些包含按钮。

SectionHeader.js

import { FormAnswersContext, FormQuestionsContext } from "../../Store";

function SectionHeader({ title, name }) {
  const [formAnswers, setFormAnswers] = useContext(FormAnswersContext);
  const [formQuestions, setFormQuestions] = useContext(FormQuestionsContext);

  return (
    <div>
      <h1 className={styles["Header"]}>{title}</h1>
      <div className={styles["MarkAllWrapper"]}>
        <button className={styles["MarkAll"]}>
          Mark all items as "Good" in this section
        </button>
        <br />
        <button className={styles["MarkAll"]}>
          Mark all items as "N/A" in this section
        </button>
      </div>
    </div>
  );
}

Section Header 的父级和表单代码的其余部分不包括我已经解释过的子单选按钮,在另一个组件中 LivingRoom.js

LivingRoom.js

import { FormQuestionsContext, FormAnswersContext } from "../../Store";

function LivingRoomForm({ Name }) {
  const [expanded, setExpanded] = useState(false);
  const [formQuestions, setFormQuestions] = useContext(FormQuestionsContext);
  const [formAnswers, setFormAnswers] = useContext(FormAnswersContext);
  const array = formQuestions.living;
  const onChange = (e, name) => {
    const { value } = e.target;
    setFormAnswers((state) => ({
      ...state,
      [Name]: { ...state[Name], [name]: value },
    }));
  };
  const handleOpen = () => {
    setExpanded(!expanded);
  };
  return (
    <div>
      <Button
        className={styles["CollapseBtn"]}
        onClick={handleOpen}
        style={{ marginBottom: "1rem", width: "100%" }}
      >
        <p>LIVING ROOM INSPECTION</p>
        <FontAwesome
          className="super-crazy-colors"
          name="angle-up"
          rotate={expanded ? null : 180}
          size="lg"
          style={{
            marginTop: "5px",
            textShadow: "0 1px 0 rgba(0, 0, 0, 0.1)",
          }}
        />
      </Button>
      <Collapse className={styles["Collapse"]} isOpen={expanded}>
        <Card>
          <CardBody>
            {array ? (
              <div>
                <SectionHeader title="Living Room Inspection" name={Name} />
                <div
                  className={styles["LivingRoomFormWrapper"]}
                  id="living-room-form"
                >
                  {array.map((question, index) => {
                    const selected =
                      formAnswers[Name] && formAnswers[Name][question]
                        ? formAnswers[Name][question]
                        : "";
                    return (
                      <div className={styles["CheckboxWrapper"]} key={index}>
                        <h5>{question}</h5>
                        <Ratings
                          section={Name}
                          question={question}
                          onChange={onChange}
                          selected={selected}
                        />
                      </div>
                    );
                  })}
                </div>
                <br />
                <ImageUploader name="living" title={"Living Room"} />
              </div>
            ) : (
              <div></div>
            )}
          </CardBody>
        </Card>
      </Collapse>
    </div>
  );
}

如果我缺少任何东西,请告诉我,我很乐意分享。干杯

编辑:适用于需要单选按钮组件的任何人。

Ratings.js

import React from "react";
import { FormGroup, CustomInput } from "reactstrap";

function Ratings({ selected, section, question, onChange }) {
  return (
    <div>
      <FormGroup>
        <div>
          <CustomInput
            checked={selected === "Good"}
            onChange={(e) => onChange(e, question)}
            type="radio"
            id={`${section}_${question}_Good`}
            value="Good"
            label="Good"
          />
          <CustomInput
            checked={selected === "Fair"}
            onChange={(e) => onChange(e, question)}
            type="radio"
            id={`${section}_${question}_Fair`}
            value="Fair"
            label="Fair"
          />
          <CustomInput
            checked={selected === "Poor"}
            onChange={(e) => onChange(e, question)}
            type="radio"
            id={`${section}_${question}_Poor`}
            value="Poor"
            label="Poor"
          />
          <CustomInput
            checked={selected === "N/A"}
            onChange={(e) => onChange(e, question)}
            type="radio"
            id={`${section}_${question}_NA`}
            value="N/A"
            label="N/A"
          />
        </div>
      </FormGroup>
    </div>
  );
}

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    经过几次尝试,我找到了解决这个问题的办法。

    这里的关键是找出一种方法来收集每个问题,以便在设置状态时可以将其用作键。由于我的问题存储在 ContextAPI 中,因此我能够像这样将它们提取出来......

    这可能不是最好的解决方案,但它对我有用。

      const setStateGood = () => {
        formQuestions[name].map((question) => {
          setFormAnswers((state) => ({
            ...state,
            [name]: { ...state[name], [question]: "Good" },
          }));
        });
      };
      const setStateNA = () => {
        formQuestions[name].map((question) => {
          setFormAnswers((state) => ({
            ...state,
            [name]: { ...state[name], [question]: "N/A" },
          }));
        });
      };
    

    我能够映射每个问题,因为 name 正在通过 props 是实际对象 formQuestions[name] 内的一个键。因为我正在映射每个问题,所以我可以将该问题设置为一个键,并将每个问题的新状态返回到我想要的任何状态。

    但是,如果我要创建一个 onClick={setState('Good')},React 不喜欢这样,它会创建一个无限循环。如果我找到了,我会寻找更多的解决方案并更新这篇文章。

    【讨论】:

      【解决方案2】:

      我不完全理解你的问题,很抱歉,但我认为这会对你有所帮助。 这是使用反应的单选按钮的实现 -

      class App extends React.Component {
        constructor(props) {
          super(props);
          this.state = {};
        }
      
        handleChange = e => {
          const { name, value } = e.target;
      
          this.setState({
            [name]: value
          });
        };
      
        render() {
          return (
            <div className="radio-buttons">
              Windows
              <input
                id="windows"
                value="windows"
                name="platform"
                type="radio"
                onChange={this.handleChange}
              />
              Mac
              <input
                id="mac"
                value="mac"
                name="platform"
                type="radio"
                onChange={this.handleChange}
              />
              Linux
              <input
                id="linux"
                value="linux"
                name="platform"
                type="radio"
                onChange={this.handleChange}
              />
            </div>
          );
        }
      }
      

      【讨论】:

      • 我有,我只需要实现一个检查所有按钮。我添加了我自己目前拥有的单选按钮。这里的目标是在设置状态时从另一个组件检查每个问题的一个单选按钮 out 4。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      • 2019-05-29
      • 2015-10-31
      • 2016-05-08
      • 2012-12-28
      • 2012-03-08
      相关资源
      最近更新 更多