Keerthana Jayakumar
Keerthana Jayakumar

Reputation: 35

Rendered fewer hooks than expected. This may be caused by an accidental early return statement in React Hooks

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'

Upvotes: 2

Views: 710

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 371019

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.

Upvotes: 1

Related Questions