Home > Enterprise >  Rendered fewer hooks than expected. This may be caused by an accidental early return statement in Re
Rendered fewer hooks than expected. This may be caused by an accidental early return statement in Re

Time:11-20

The following component throws me this error message at runtime when I try to render the table as Input value (editable field) with the additional warning given below.

Warning: Do not call Hooks inside useEffect(...), useMemo(...), or other built-in Hooks. You can only call Hooks at the top level of your React function.

This is my code,

const EditableCell = (initialValue: any) => {
  const [value, setValue] = React.useState(initialValue);

  const onChange = (e: any) => {
    setValue(e.target.value);
  };

  React.useEffect(() => {
    setValue(initialValue);
  }, [initialValue]);

  return <Input type="text" value={value} onChange={onChange} />;
};


const ParameterTable: React.FC<ParameterTableProps> = () => {
  const {
    decisionMetadataInput: input,
    decisionMetadataOutput: output,
    paramList
  } = testData.data;
  const inMeta = React.useMemo(() => input?.metadata ?? [], [input]);
  const outMeta = React.useMemo(() => output?.metadata ?? [], [output]);
  const allColumn = React.useMemo(
    () =>
      [...inMeta, ...outMeta].map((meta) => (
        <Column
          title={
            <>
              <span>{meta.field}</span>
              <br />
              <Typography.Text italic>({meta.type})</Typography.Text>
            </>
          }
          key={meta.field}
          dataIndex={["data", meta.field]}
          render={(dataIndex) => EditableCell(dataIndex)}
        />
      )),
    [inMeta, outMeta]
  );
  const datasource = React.useMemo(
    () =>
      paramList.map((param) => {
        const inParam = param?.paramInput?.param ?? [];
        const outParam = param?.paramOutput?.param ?? [];
        const data = [...inParam, ...outParam].reduce(
          (prev, current) => ({
            ...prev,
            [current.field]: current.value
          }),
          {}
        );
        return { data, num: param.paramOrder };
      }),
    [paramList]
  );

  return (
    <Table dataSource={datasource} rowKey="num" pagination={false}>
      <Column title="F" dataIndex="num" />
      {allColumn}
    </Table>
  );
};

This is my codesandbox URL - https://codesandbox.io/s/react-typescript-forked-hl179m?file=/src/ParameterTable.tsx

I suspect this happens because I call the function EditableCell inside the useMemo hook, however I'm not sure how to resolve this. Any help/ suggestion would do, thanks.

I'm trying to make the Antd React Table as editable fields, however when I tried to map the dataIndex as value in a seperate function to render in the column I get this 'Uncaught Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement in React Hooks'

CodePudding user response:

Instead of calling EditableCell as if it were a plain function, wrap it in React.createElement so that React can see that it's a component (and can therefore have hooks called inside it).

Change to

render={(dataIndex) => <EditableCell initialValue={dataIndex} />}

and

const EditableCell = ({ initialValue }: { initialValue: any }) => {

It would also be a good idea to avoid any, which defeats the purpose of using TypeScript - wherever you have an any, identify the actual type that'll be used there, and use that type instead.

  • Related