【问题标题】:How to change label's style when I change radio inputs?更改收音机输入时如何更改标签的样式?
【发布时间】:2021-10-14 12:08:26
【问题描述】:

我创建了类名“OccupancyChecked”,以便将其应用于检查的收音机标签,但由于某种原因我无法使其工作。

这是风格:

const Occupancy = styled.label`
  //more code

  .OccupancyChecked {
    border: 1px solid rgba(255, 255, 255, 0.24);
    background: #7f5cf1;
  }
`;

下面是调用上面的className的代码。我试图做的是:只有两个收音机,所以我在第一个收音机上插入了一个onChange,结果在每个标签的类名中,如果收音机是checked或空白,它应该调用"Occupancy"类名否则,类名。我相信这个逻辑应该有效,但事实并非如此。我还创建了一个sandbox,以便显示正在运行的代码。

export default function App() {
  const [occupancyChecked, setOccupancyChecked] = useState(0);

  function changeOccupancyChecked() {
    occupancyChecked === 0 ? setOccupancyChecked(1) : setOccupancyChecked(0);
    return;
  }

  return (
    <div className="App">
      <Occupancy>
        <label
          htmlFor="radioTeacher"
          className={occupancyChecked === 0 ? "OccupancyChecked" : ""}
        >
          <input
            type="radio"
            name="occupancy"
            id="radioTeacher"
            onChange={changeOccupancyChecked}
            checked
          />
          <span>I'm a teacher</span>
        </label>
        <label
          htmlFor="radioStudant"
          className={occupancyChecked === 1 ? "OccupancyChecked" : ""}
        >
          <input type="radio" name="occupancy" id="radioStudant" />
          <span>I'm a studant</span>
        </label>
      </Occupancy>
    </div>
  );
}

如何解决这个问题?在选中的收音机中显示 className OccupancyChecked

【问题讨论】:

    标签: reactjs typescript radio-button label styled-components


    【解决方案1】:

    radioTeacher 中默认的checked 是主要原因。我已经更新了它以便更好地理解。

    Working link

    import "./styles.css";
    import styled from "styled-components";
    import { useEffect, useState } from "react";
    
    const Occupancy = styled.label`
      display: flex;
      justify-content: space-between;
      margin-bottom: 1rem;
      font-size: 0.7rem;
      font-family: "Open Sans", sans-serif;
      font-weight: 400;
    
      label {
        border: 1px solid #6f49ed;
        background: #6f49ed;
        border-radius: 4px;
        padding: 1rem;
        text-transform: uppercase;
        width: 48%;
    
        input {
        }
    
        span {
          margin-left: 0.4rem;
        }
      }
      .OccupancyChecked {
        border: 1px solid rgba(255, 255, 255, 0.24);
        background: red;
      }
    `;
    
    export default function App() {
      const [occupancyChecked, setOccupancyChecked] = useState(0);
    
      const changeOccupancyChecked = (val) => {
        console.log("Value to set:", val);
        setOccupancyChecked(val);
        //occupancyChecked === 0 ? setOccupancyChecked(1) : setOccupancyChecked(0);
        //return;
      };
    
      return (
        <div className="App">
          <Occupancy>
            <label
              htmlFor="radioTeacher"
              className={occupancyChecked === 0 ? "OccupancyChecked" : ""}
            >
              <input
                type="radio"
                name="occupancy"
                id="radioTeacher"
                onChange={() => {
                  changeOccupancyChecked(0);
                }}
              />
              <span>I'm a teacher</span>
            </label>
            <label
              htmlFor="radioStudant"
              className={occupancyChecked === 1 ? "OccupancyChecked" : ""}
            >
              <input
                type="radio"
                name="occupancy"
                id="radioStudant"
                onChange={() => {
                  changeOccupancyChecked(1);
                }}
              />
              <span>I'm a studant</span>
            </label>
          </Occupancy>
        </div>
      );
    }

    【讨论】:

    • 这段代码只有一个问题,没有一个输入以checked开头,这是原代码中发生的事情
    • 我已经更新了示例,添加了checked={occupancyChecked === 0} 和checked={occupancyChecked === 1},因此它将相应地从选择开始。 @MestreALMO
    【解决方案2】:

    我确实重构了您的代码以更灵活。 working example

    1. 我为按钮创建了初始属性
    2. 单独制作button组件
    3. changeOccupancyChecked 函数和Button 组件的接口添加了type
    4. div 创建了wrapper。您确实将 label 作为包装器,这是错误的。在这种情况下,您需要在第一次渲染时按两次按钮。

    好方法

    input {
      width: 50px;
      height: 50px
    }
    <div id="wrapper">
      <label>
            <input type="checkbox"/>
          </label>
      <label>
            <input type="checkbox"/>
          </label>
    </div>

    不好的方法

    input {
      width: 50px;
      height: 50px
    }
    <label id="wrapper">
          <label>
            <input type="checkbox"/>
          </label>
    <label>
            <input type="checkbox"/>
          </label>
    </label>

    正如您在第二个 sn-p 中看到的,当您单击第二个 checkdox 时,两个复选框都闪烁了。当然这也可以,但有时这种行为是不可预测的。

    App.tsx sn-p

    import styled, { css } from "styled-components";
    import { useState, ChangeEvent, FC } from "react";
    
    interface ButtonsPropsType {
      isChecked: boolean;
      index: number;
      id: string;
      changeOccupancyChecked: (ev: ChangeEvent<HTMLInputElement>) => void;
    }
    
    const ButtonsWrapper = styled.div`
      display: flex;
      justify-content: space-between;
      margin-bottom: 1rem;
      font-size: 0.7rem;
      font-family: "Open Sans", sans-serif;
      font-weight: 400;
    `;
    const Occupancy = styled.label<{ checked: boolean }>`
      max-width: 250px;
      border: 1px solid #6f49ed;
      background: #6f49ed;
      border-radius: 4px;
      padding: 1rem;
      text-transform: uppercase;
      width: 48%;
      ${({ checked }) =>
        checked &&
        css`
          border: 1px solid rgba(255, 255, 255, 0.24);
          background: #7f5cf1;
        `}
      span {
        margin-left: 0.4rem;
        color: white;
        font-weight: bold;
      }
    `;
    
    // Button component
    export const Button: FC<ButtonsPropsType> = ({
      isChecked,
      changeOccupancyChecked,
      id,
      index,
      children
    }) => {
      return (
        <Occupancy checked={isChecked}>
          <input
            type="radio"
            name="occupancy"
            id={id}
            onChange={changeOccupancyChecked}
            checked={isChecked}
            data-index={index}
          />
          <span>{children}</span>
        </Occupancy>
      );
    };
    
    // Buttons properties
    const initialButtonState = [
      { id: "radioTeacher", name: "I'm a teacher", select: true },
      { id: "radioStudant", name: "I'm a studant", select: false },
      { id: "radioCustomer", name: "I'm a customer", select: false }
    ];
    
    export default function App() {
      const [occupancyChecked, setOccupancyChecked] = useState(0);
      const [isChecked, setIsChecked] = useState("radioTeacher");
    
      const changeOccupancyChecked = (ev: ChangeEvent<HTMLInputElement>) => {
        setIsChecked(ev.target.id);
        setOccupancyChecked(Number(ev.target.getAttribute("data-index")));
      };
    
      return (
        <div className="App">
          <h3>{occupancyChecked}</h3>
          <ButtonsWrapper>
            {initialButtonState.map((button, index) => {
              return (
                <Button
                  key={button.id}
                  changeOccupancyChecked={changeOccupancyChecked}
                  isChecked={button.id.includes(isChecked)}
                  id={button.id}
                  index={index}
                >
                  {button.name}
                </Button>
              );
            })}
          </ButtonsWrapper>
        </div>
      );
    }
    

    【讨论】:

      猜你喜欢
      • 2020-01-01
      • 2017-11-20
      • 1970-01-01
      • 2023-02-13
      • 2021-11-22
      • 1970-01-01
      • 1970-01-01
      • 2021-08-26
      • 1970-01-01
      相关资源
      最近更新 更多