重新渲染过多。在useState()中使用switch语句

时间:2019-12-19 08:53:26

标签: javascript reactjs

我有一个ErrorBox组件,它仅显示具有指定属性的错误。预期的输出应该是根据ErrorReason它将显示相关的颜色,图标和信息

const ErrorBox = ({ ErrorReason }) => {

  const [status, setStatus] = useState({})
  switch (ErrorReason) {
    case "wrong-password":
      setStatus({
        icon: "lock",
        info: "Incorrect password",
        color: "#fff"
      });
      break;
    case "invalid-email":
      setStatus({
        icon: "cross",
        info: "Invalid email",
        color: "#000"
      });
      break;
    case "too-many-request":
      setStatus({
        icon: "user",
        info: "Too many incorrect requests",
        color: "#bbb"
      });
      break;
  }

  return (
    <div >
       <Icon
        type={status.icon}
        style={{ color: `${status.color}` }}
      />
      {status.info} 
    </div>
  );
};

2 个答案:

答案 0 :(得分:3)

问题是您从状态let filteredArray = array.filter { $0.name.lowercased().contains("ata") } 开始,然后立即对其进行修改。

您完全不需要在这里声明 。只需使用错误原因即可:

{}

但是如果您 did 需要状态,则需要先进行const ErrorBox = ({ ErrorReason }) => { let icon, info, color; switch (ErrorReason) { case "wrong-password": icon = "lock"; info = "Incorrect password"; color = "#fff"; break; case "invalid-email": icon = "cross"; info = "Invalid email"; color = "#000"; break; case "too-many-request": icon = "user"; info = "Too many incorrect requests"; color = "#bbb"; break; default: // Must throw here throw new Error(`Invalid ErrorReason: ${ErrorReason}`); } return ( <div > <Icon type={icon} style={{ color: `${color}` }} /> {info} </div> ); }; ,然后使用该值作为状态的初始值:

switch

我认为我根本不会使用// If you needed state for some reason (you don't below) const ErrorBox = ({ ErrorReason }) => { let initialStatus; switch (ErrorReason) { case "wrong-password": initialStatus = { icon: "lock", info: "Incorrect password", color: "#fff" }; break; case "invalid-email": initialStatus = { icon: "cross", info: "Invalid email", color: "#000" }; break; case "too-many-request": initialStatus = { icon: "user", info: "Too many incorrect requests", color: "#bbb" }; break; default: // Must throw here throw new Error(`Invalid ErrorReason: ${ErrorReason}`); } const [status, setStatus] = useState(initialStatus); return ( <div > <Icon type={status.icon} style={{ color: `${status.color}` }} /> {status.info} </div> ); }; 来将switch映射到错误信息,我会使用地图(或使用ErrorReason创建的对象) :

Object.create(null)

然后该组件就是:

const statusInfoMap = new Map([
  [
    "wrong-password",
    {
        icon: "lock",
        info: "Incorrect password",
        color: "#fff"
    }
  ],
  [
    "invalid-email",
    {
      icon: "cross",
      info: "Invalid email",
      color: "#000"
    }
  ],
  [
    "too-many-request",
    {
      icon: "user",
      info: "Too many incorrect requests",
      color: "#bbb"
    }
  ]
]);

实时示例:

const ErrorBox = ({ ErrorReason }) => {
  const status = statusInfoMap.get(ErrorReason);
  if (!status) {
    throw new Error(`Invalid ErrorReason: ${ErrorReason}`);
  }

  const {icon, color, info} = status;
  return (
    <div >
       <Icon
        type={icon}
        style={{ color: `${color}` }}
      />
      {info} 
    </div>
  );
};
const {useState, useCallback} = React;

const statusInfoMap = new Map([
  [
    "wrong-password",
    {
        icon: "lock",
        info: "Incorrect password",
        color: "#fff"
    }
  ],
  [
    "invalid-email",
    {
      icon: "cross",
      info: "Invalid email",
      color: "#000"
    }
  ],
  [
    "too-many-request",
    {
      icon: "user",
      info: "Too many incorrect requests",
      color: "#bbb"
    }
  ]
]);

const ErrorBox = ({ ErrorReason }) => {
  const status = statusInfoMap.get(ErrorReason);
  if (!status) {
    throw new Error(`Invalid ErrorReason: ${ErrorReason}`);
  }

  const {icon, color, info} = status;
  return (
    <div >
       icon: {icon}, color: {color}, info: {info}
    </div>
  );
};

const errors = [
  "wrong-password",
  "invalid-email",
  "too-many-request",
];
const Example = () => {
    const [index, setIndex] = useState(0);
    const error = errors[index];
    
    const onClick = useCallback(() => {
        setIndex(index + 1);
    }, [index]);

    return (
        <div>
            <ErrorBox ErrorReason={error} />
            {index < errors.length - 1
            ? <input type="button" value="Next" onClick={onClick} />
            : <input type="button" value="Start Again" onClick={() => setIndex(0)} />
            }
        </div>
    );
};

ReactDOM.render(<Example />, document.getElementById("root"));

或者如果您需要状态来显示您未显示的内容:

<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>

答案 1 :(得分:-1)

仅应在ErrorReason更改时执行状态更新。在这种情况下,请使用useEffect钩子并将ErrorReason添加为依赖项。

useEffect(() => {
 switch (ErrorReason) {
    case "wrong-password":
      setStatus({
        icon: "lock",
        info: "Incorrect password",
        color: "#fff"
      });
      break;
    case "invalid-email":
      setStatus({
        icon: "cross",
        info: "Invalid email",
        color: "#000"
      });
      break;
    case "too-many-request":
      setStatus({
        icon: "user",
        info: "Too many incorrect requests",
        color: "#bbb"
      });
      break;
  }
}, [ErrorReason])

更新: 为了避免局部状态和变量。

const ErrorBox = ({ ErrorReason }) => {

  const getData = () => {
switch (ErrorReason) {
    case "wrong-password":
      return ({
        icon: "lock",
        info: "Incorrect password",
        color: "#fff"
      });
    case "invalid-email":
      return ({
        icon: "cross",
        info: "Invalid email",
        color: "#000"
      });
    case "too-many-request":
      return ({
        icon: "user",
        info: "Too many incorrect requests",
        color: "#bbb"
      });
  }}


  return (
    <div >
       <Icon
        type={status.icon}
        style={{ color: `${status.color}` }}
      />
      {getData().info} 
    </div>
  );
};