【问题标题】:prevent re render with hooks防止用钩子重新渲染
【发布时间】:2020-07-14 14:00:08
【问题描述】:

我正在处理表格内的切换按钮状态。当对 api 的请求失败时,我需要返回错误并且检查的状态不能改变。

Checked 由来自 api 的特定数据控制。发生的情况是,当 setErrors 重新渲染组件时,我认为这是切换按钮更改的原因。

 async function handleStatus(groups, status, id) {
    const response = await chengeStatus(groups, status, id);
    const { status: state, data, message } = response;

    if (state) {
      setGroups(data);
      return true;
    } else {
      setErrors({
        status: true,
        message: message,
      });
      return false;
    }
  }

切换按钮:

const columns = [
    {
      cell: (row) => {
        return (
          <Switch
            checked={row.enable}
            handleChange={() => handleStatus(groups, row.enable, row.id)}
          ></Switch>
        );
      },
      width: "80px",
    },
  ];

错误显示:

 return(
     {errors.status &&
      <Alert
      message="Erro"
      description={errors.message}
      type="error"
      showIcon
      />
      } 
    )

【问题讨论】:

  • if (state) { 这个state 来自哪里?
  • @MayankPandeyz 来自 chengeStatus 函数,调用 API
  • @MayankPandeyz 我解构并将状态名称分配给状态
  • @MayankPandeyz 将status 改名为state const { status: state } = response;
  • 它存在,伙计。当我这样做时 {status : state} 我有点像@AllenWong 所说的那样给了它一个“昵称”。

标签: reactjs react-hooks react-lifecycle


【解决方案1】:

通过阻止重新渲染来解决这个问题并不是一个好主意。

你需要做的应该是把checked={row.enable}改成defaultChecked={row.enable}

将默认值传递给并为真正的检查状态创建另一个钩子:

const Switch = ({ defaultChecked, handleChange }) => {
  const [checked, setChecked] = useState(defaultChecked);

  useEffect(() => {

    setChecked(defaultChecked);

  }, [defaultChecked]); // Update the state if props change again.

  const onToggle = () => {
    handleChange(!checked);
    setChecked(!checked);
  }

  return <Comp checked={checked} onToggle={onToggle} />; // TODO show you the idea only
}

所以点击后检查的值将保持不变,直到您重新获取row数据。

【讨论】:

  • handleChange(!checked); 这样您就可以通过handleChange={(isChecked) =&gt; handleStatus(groups, isChecked, row.id)} 将新状态用作您的 api 数据,因为 row.enable 在您重新获取它之前不会更新,如果您的用户反复切换开关,它就不那么可靠了短时间内
  • 我按照你说的做了,但有点不同......
  • 首先添加名称道具来切换组件并将检查更改为您所说的默认检查...所以当请求失败时: const obj = {...checked} obj[id] = status setChecked(obj )
  • oic,因此您可以将 onToggle 作为异步函数,并等待最终 setChecked 的响应结果。 const onToggle = async () =&gt; { const result = await handleChange(!checked); setChecked(result); }
【解决方案2】:

我想分享解决方案,正如@AllenWong 所说,防止重新渲染,这不是处理这种情况的最佳途径。

我对defaultValue的作用有点迷茫,查了一下..

所以,正如艾伦所说,我将 checked={row.enable} 更改为 defaultValue={row.enable} 并创建了已检查的钩子。

但我必须控制检查状态有点不同,因为我有多个检查状态要控制。

所以,我添加了 name 属性来切换组件

<Switch
   name={row.id}  
   checked={checked[row.id]}
   defaultChecked={row.enable}
   handleChange={() => handleStatus(groups, row.enable, row.id)}>
 </Switch>

当请求失败时:

const obj = {...checked} 
  obj[id] = status
      setChecked(obj)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-23
    • 1970-01-01
    • 2016-07-26
    • 2019-10-17
    • 2021-06-08
    • 2020-03-09
    • 2020-06-27
    • 1970-01-01
    相关资源
    最近更新 更多