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.
