与 TypeScript 反应:如何使用先前的状态输入 useState 钩子

时间:2021-07-28 10:38:15

标签: reactjs typescript

我有一个 React + TS 应用程序,我正在编写一个自定义钩子来更新表的标题。基本上,我可以点击不同的复选框并隐藏/显示表格的特定列。

const useHeader = (headerConfiguration: TableHeader[]) => {
  const [header, setHeader] = useState(headerConfiguration);

  const updateHeader = (column: string) => {
     setHeader(prevState => {                       // <- this line has the error
       prevState.forEach(el => {
         if (el.name === column) el.visible = !el.visible;
       });
     });
  };

  return {
    header,
    updateHeader,
  };
};

export default useHeader;

如代码所示,我需要根据 visible 名称更新 column 属性。

目前我有一个错误:

<块引用>

'(prevState: TableHeader[]) => void' 类型的参数不是 可分配给“SetStateAction”类型的参数。
类型 '(prevState: TableHeader[]) => void' 不可分配给类型 '(prevState: TableHeader[]) => TableHeader[]'。 类型“void”不可分配给类型“TableHeader[]”。

我明白错误的意思,但我不知道如何修复它,如果我使用库 Immer 编写相同的函数,它可以正常工作:

   setHeader(
     produce(header, draftHeader => {
       draftHeader.forEach(el => {
         if (el.name === column) {
           el.visible = !el.visible;
         }
       });
     }),
   );

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:2)

不使用 immer 时,您有责任产生返回一个状态。因此,您需要创建它的副本,并应用您需要的更改,而不是操作 prevState

例如,像这样:

const updateHeader = (column: string) => {
  setHeader(prevState => {
    // return a copy prevState
    return prevState.map(
      el => el.name === column
        ? {...el, visible: !el.visible} // copy inner item, if changed
        : el;
    );
  });
};

答案 1 :(得分:0)

请试试这个:

const useHeader = (headerConfiguration: TableHeader[]) => {


const [header, setHeader] = useState(headerConfiguration);



const updateHeader = (column: string) => {
    header.forEach(el => {
      if (el.name === column) el.visible = !el.visible;
    });
    setHeader(header);
  };

  return {
    header,
    updateHeader,
  };
};

export default useHeader;