简体   繁体   English

如何使用 React Hooks 实现单选按钮的检查所有按钮?

[英]How to implement a check all button for radio buttons, using React Hooks?

Don't get this confused with checking each radio button I have on the page.不要与检查页面上的每个单选按钮混淆。 I want to implement a check all button that sets the value of a nested object state equal to a certain value.我想实现一个check all button ,将嵌套 object state 的值设置为某个值。 I am storing each question in a nested state.我将每个问题存储在嵌套的 state 中。 Ex.前任。

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

Four radio buttons are being made for each question.每个问题都制作了四个单选按钮。 Now one radio button can only be selected at once.现在一次只能选择一个单选按钮。 Each radio button has its' own value.每个单选按钮都有自己的值。 Ex.前任。 `"Good", "Fair", "Poor", "N/A". `“好”、“一般”、“差”、“不适用”。

When a radio button is selected a state is generated dynamically for that section and question.选择单按钮时,state是为该部分和问题动态生成的。 Ex.前任。

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

The goal here is the button that I want to create that checks only one value for each question Ex.这里的目标是我要创建的按钮,它只检查每个问题 Ex 的一个值。 clicks button question: "Good", question2: "Good" etc..点击按钮question: "Good", question2: "Good"等。

For me to set the state of a dynamic value I would need the "Section name" lets call it Name and the "Question" we'll call it question .对我来说,将 state 设置为动态值,我需要“Section name”让我们称之为Name和“Question”我们称之为question That would give me access to the value like so formAnswers[Name][question]: value这将使我能够像这样访问值formAnswers[Name][question]: value

I am trying to set that state from a component called SectionHeader .我正在尝试从名为 SectionHeader 的组件中设置SectionHeader These contain the buttons.这些包含按钮。

SectionHeader.js 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>
  );
}

The parent of Section Header and the rest of the form code excluding the child radio buttons which I have explained, are in another component LivingRoom.js Section Header的父级和表单代码的 rest不包括我已经解释的子单选按钮,位于另一个组件LivingRoom.js

LivingRoom.js客厅.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>
  );
}

If there is anything I am missing please let me know, I would be happy to share it.如果有什么我想念的,请告诉我,我很乐意分享。 Cheers干杯

Edit: for anyone that needs the radio buttons component.编辑:适用于需要单选按钮组件的任何人。

Ratings.js 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>
  );
}

I do not completely understand your question, I am sorry but I think this will help you.我不完全理解你的问题,很抱歉,但我认为这会对你有所帮助。 Here is an implementation of radio buttons using react -这是使用反应的单选按钮的实现 -

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>
    );
  }
}

After a few attempts, I was able to figure out the solution to this issue.经过几次尝试,我能够找出解决此问题的方法。

The key here was to figure out a way to get gather each question so that it may be used as a key when setting the state.这里的关键是想办法收集每个问题,以便在设置 state 时将其用作关键。 As my questions were stored in a ContextAPI, I was able to pull them out like so...由于我的问题存储在 ContextAPI 中,因此我能够像这样将它们拉出来......

this may not be the best solution however it worked for me.这可能不是最好的解决方案,但它对我有用。

  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" },
      }));
    });
  };

I was able to map through each question since the name is being passed through props is a key inside the actual object, formQuestions[name] .我能够通过每个问题 map ,因为name正在通过道具是实际 object 中的一个键, formQuestions[name] Because i'm mapping through each one I can set that question as a key and return the new state for each question to whatever I would like.因为我正在映射每个问题,所以我可以将该问题设置为一个键,并将每个问题的新 state 返回到我想要的任何问题。

However, if I was to create an onClick={setState('Good')} , React didn't like that and it created an infinite loop.但是,如果我要创建一个onClick={setState('Good')} ,React 不喜欢这样,它会创建一个无限循环。 I will look for more solutions and update this post if I find one.如果我找到一个,我会寻找更多的解决方案并更新这篇文章。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM