简体   繁体   English

太多的重新渲染。 将 switch 语句与 useState() 一起使用

[英]Too many re-renders. Using switch statement with useState()

I have an ErrorBox component that is purely displaying the error with the specified attributes.我有一个 ErrorBox 组件,它纯粹显示具有指定属性的错误。 The expected output should be that depending on the ErrorReason it will display the associated color, icon and info预期的输出应该是根据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>
  );
};

The problem is that you're starting with the state {} and then immediately modifying it.问题是您从状态{} ,然后立即修改它。

You don't need to want state here at all.你根本不需要状态在这里。 Just use the error reason:只需使用错误原因:

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

But if you did need state, you'd do the switch first and then use the value as the initial value of the state:但是,如果您确实需要状态,则可以先进行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>
  );
};

I don't think I'd use a switch to map the ErrorReason to error information at all, I'd use a map (or an object created with Object.create(null) ):我认为我根本不会使用switchErrorReason映射到错误信息,我会使用映射(或使用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"
    }
  ]
]);

Then the component is just:那么组件就是:

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

Live Example:现场示例:

 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>

Or if you need state for something you haven't shown:或者,如果您需要未显示的内容的状态:

const ErrorBox = ({ ErrorReason }) => {
  const initialStatus = statusInfoMap.get(ErrorReason);
  if (!initialStatus) {
    throw new Error(`Invalid ErrorReason: ${ErrorReason}`);
  }
  const [status, setStatus] = useState(initialStatus);

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

You should perform state update only when ErrorReason changes.仅当ErrorReason更改时才应执行状态更新。 In this scenario use useEffect hook and add ErrorReason as dependency.在这种情况下,使用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])

Update: To avoid local state and variables.更新:避免局部状态和变量。

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

暂无
暂无

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

相关问题 useState 和 if 语句导致错误:重新渲染太多。 React 限制渲染次数以防止无限循环 - useState and if statement causing Error: Too many re-renders. React limits the number of renders to prevent an infinite loop 太多的重新渲染。 React 限制了渲染的数量以防止无限循环。 使用状态问题? - Too many re-renders. React limits the number of renders to prevent an infinite loop. useState problem? 反应使用状态错误:重新渲染太多。 React 限制渲染次数以防止无限循环 - react usestate Error: Too many re-renders. React limits the number of renders to prevent an infinite loop 太多的重新渲染。 在 React Native 中 - Too many re-renders. in React Native 如何解决使用 useState 的 function 调用并获得“太多重新渲染。 反应过来……” - How to solve a function call that uses useState with getting “Too many re-renders. React…” 为什么 useState react hook 会导致过多的重新渲染。 React 限制渲染次数以防止无限循环 - Why does useState react hook cause Too many re-renders. React limits the number of renders to prevent an infinite loop 太多的重新渲染。 React 限制渲染的数量 - Too many re-renders. React limits the number of renders 错误:重新渲染过多。 React 限制渲染次数 - Error: Too many re-renders. React limits the number of renders 为什么我收到“未捕获的错误:重新渲染次数过多”。 在尝试使用 useState 将一个从自定义挂钩中获得的常量分配给另一个常量时? - Why I am getting 'Uncaught Error: Too many re-renders.' while a try to assign a const that a got from custom hook into another const using useState? 错误:重新渲染过多。 因为我改变了 setState - Error: Too many re-renders. because i changed setState
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM