Home > Mobile >  React Hook "useState" is called inside condition, but not condition is inside
React Hook "useState" is called inside condition, but not condition is inside

Time:01-20

After to read this page: https://typeofnan.dev/fix-the-react-hook-is-called-conditionally-error-in-react/

I try to find the error but i keep getting the error:

React Hook "useState" is called conditionally

here the code:

export const PageSettings = (props) => {
  const {
    table,
    listviewFields,
    t,
    tableCrud,
    updatePageSettingsFields,
    templates,
    visibleFields,
    visibleFieldsToggle,
  } = props;

  let aFields = [];
  let aFieldsForSortable = [];
  for (const [keyName, fieldSet] of Object.entries(listviewFields)) {
    const listViewField = table.listview.fields[keyName];
    let fieldSource;
    if (listViewField.virtual) {
      // virtual don't throw error, must have always label
      fieldSource = listViewField;
    } else {
      fieldSource = table.fields[keyName];
    }
    const field = table.fields[keyName];

    const { aColHeaderToAdd, titleFieldFull, printCell } = getHeaderToAdd(
      listViewField,
      keyName,
      fieldSource,
      table,
      props,
      t,
      templates,
      tableCrud,
      fieldSet,
      listviewFields
    );

    if (printCell) {
      aFieldsForSortable.push({ id: keyName, name: titleFieldFull });
      aFields.push(
        <div
          key={keyName}
          style={{
            fontSize: "12px",
            minWidth: "90px",
            maxWidtht: "150px",
            bgColor:
              listviewFields && listviewFields[keyName].invisible === true
                ? "black"
                : "green",
          }}
        >
          <input
            type="checkbox"
            name={keyName}
            style={{}}
            checked={
              !listviewFields[keyName].invisible ||
              listviewFields[keyName].invisible === false
                ? true
                : false
            }
            onChange={updatePageSettingsFields}
          />
          <label htmlFor={keyName}>{titleFieldFull}</label>
        </div>
      );
    }
  }

  const [stateList, setStateList] = useState([aFieldsForSortable]);

  return (
    <div
      style={{
        display: "flex",
        flexDirection: "row",
        alignItems: "center",
        color: "#FFFFFF",
        paddingTop: "20px",
        width: "100%",
        backgroundColor: visibleFields ? "#555555" : null,
      }}
    >
      <a onClick={visibleFieldsToggle}>
        <ShowIcon icon="eyecheck" color="#5f97c1" />
      </a>
      <ReactSortable list={stateList} setList={setStateList}>
        {state.map((item) => (
          <div key={item.id}>{item.name}</div>
        ))}
      </ReactSortable>
      {visibleFields && aFields}
    </div>
  );
};

const getHeaderToAdd = (
  listViewField,
  keyName,
  fieldSource,
  table,
  props,
  t,
  templates,
  tableCrud,
  fieldSet,
  listviewFields
) => {
  let colsHeader = [];
  let printCell = true;
  // Logic Twin TT103
  let titleField;
  let titleFieldFull;
  // fieldSource can be not exist, by example , virtual field: customers.listview.addresses2
  if (
    fieldSource &&
    fieldSource.fieldDisplayedOptions &&
    fieldSource.fieldDisplayedOptions.separatorsubfield === "col"
  ) {
    /*
  not call main field, but the subfields to get label
   */
    for (const [nameSubField, objField] of Object.entries(
      fieldSource.fieldDisplayedOptions.subfields
    )) {
      titleField = resolveListLabel(table.related[keyName].table, nameSubField); // look for related table
      titleFieldFull =
        titleFieldFull   (titleFieldFull ? " " : "")   titleField;
      colsHeader.push(
        <div className="cell" key={nameSubField   keyName}>
          {t(titleField)}
        </div>
      );
    }
  } else {
    if (listViewField.module) {
      if (
        !resolvePathObj(
          props,
          "myState.app.appSettings.modules."   listViewField.module,
          true
        )
      ) {
        //if (keyName === 'dateaccounting') console.log('module not compat', props);
        printCell = false;
      }
    }
    if (listViewField.templates) {
      if (
        !intersection(
          listViewField.templates,
          templates,
          props.tableCrud,
          keyName
        )
      ) {
        //if (keyName === 'dateaccounting') console.log('no template');
        printCell = false;
      }
    }
  }
  /*if (keyName === 'dateaccounting') {
    console.log('module, propstemplates, templates', listViewField.module, templates, listViewField.templates);
  }*/

  if (printCell) {
    titleFieldFull = resolveListLabel(tableCrud, keyName);

    // try find short word, if not exist then get normal word
    let title = t(titleFieldFull   "_short");
    if (title === titleFieldFull   "_short") title = t(titleFieldFull);
    titleFieldFull = title;

    colsHeader.push(
      <div className="cell" key={keyName}>
        {titleFieldFull}
      </div>
    );
  }
  return { titleFieldFull, printCell, colsHeader };
};

thanks

CodePudding user response:

You're passing the argument aFieldsForSortable which is initialized as [] and then conditionally (inside the if statement), you're writing information for that value.

I'd suggest starting the use state as empty and in case you're changing it, call the setStateList method. For example,

const [stateList, setStateList] = useState([]);

....

if (printCell) {
    const aFieldsForSortable = stateList;
    aFieldsForSortable.push({ id: keyName, name: titleFieldFull });
    setStateList(aFieldsForSortable);

CodePudding user response:

You are breaking the Rules of Hooks.

Rules of Hooks say:

Only Call Hooks at the Top Level
Don’t call Hooks inside loops, conditions, or nested functions

The useState() call should be at the top of your function. If your initial state is based on a complex calculation, then you should do that calculation inside useEffect() (setting the value using setStateList()), otherwise the complex calculation will be re-run every time your Component is re-rendered.

  •  Tags:  
  • Related