简体   繁体   English

React Hook“useState”被称为内部条件,但不是条件在内部

[英]React Hook "useState" is called inside condition, but not condition is inside

After to read this page: https://typeofnan.dev/fix-the-react-hook-is-called-conditionally-error-in-react/阅读此页面后: 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有条件地调用 React Hook “useState”

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谢谢

You're passing the argument aFieldsForSortable which is initialized as [] and then conditionally (inside the if statement), you're writing information for that value.您正在传递参数aFieldsForSortable ,该参数被初始化为[] ,然后有条件地(在 if 语句中),您正在为该值编写信息。

I'd suggest starting the use state as empty and in case you're changing it, call the setStateList method.我建议开始使用 state 为空,如果您要更改它,请调用setStateList方法。 For example,例如,

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

....

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

You are breaking the Rules of Hooks .你违反了钩子规则

Rules of Hooks say:钩子规则说:

Only Call Hooks at the Top Level仅在顶层调用 Hooks
Don't call Hooks inside loops, conditions, or nested functions不要在循环、条件或嵌套函数中调用 Hooks

The useState() call should be at the top of your function. useState()调用应该在 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.如果您的初始 state 是基于复杂计算,那么您应该在useEffect()中进行该计算(使用setStateList()设置值),否则每次重新渲染组件时都会重新运行复杂计算。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM