在类组件中工作,但在钩子中,val()函数调用无穷多次


function Inhook(props) {
const initialState = 0;
const [records, setRecords] = useState([]);
const [count, setCount] = useState(initialState);
const [show, setShow] = useState(false);
const [store, setStore] = useState(initialState);
const [store1, setStore1] = useState(initialState);
setRecords(props.records);
function val(e) {
debugger;
console.log("hhh", e);
setStore(e);
if (store === store1) {
if (count == 0) {
setShow(true);
} else {
setShow(false);
}
} else {
setShow(true);
setCount(0);
}
setCount(count + 1);
// console.log(count,'counttt');
setStore1(e);
}
return (
<div>
<React.Fragment>
<br />
<div className="Tree">
<h1 style={{ textAlign: "center" }}>Employee Tree</h1>
<h3>Test Case 1</h3>
<h4>Employee Tree</h4>
{
(records.sort((x, y) => (x.empName.toLowerCase() > y.empName.toLowerCase()) * 2 - 1),
records.map(empId => {
return empId.managerId === 0 ? (
<ul key={empId.id}>
<li style={{ fontWeight: "Bold" }}>
{empId.empName.toLowerCase()}
<p>Employees of : {empId.empName.toLowerCase()}</p>
<ul>
{records.map(s =>
s.managerId === empId.id ? (
<li type="square" key={s.id}>
{s.empName.toLowerCase()}
{empId.managerId === s.id ? <p>Employees of :{s.empName.toLowerCase()}</p> : <p></p>}
{records.map(e =>
e.managerId === s.id ? (
<div>
{e.managerId === s.id ? <p>{val(s.id)}</p> : <p></p>}
{show ? <p>Employees of :{s.empName.toLowerCase()}</p> : <p></p>}
<li key={e.id} type="disc" style={{ marginLeft: "120px" }}>
{e.empName.toLowerCase()}
</li>
</div>
) : (
""
)
)}
</li>
) : (
""
)
)}
</ul>
</li>
</ul>
) : (
""
);
}))
}
</div>
</React.Fragment>
</div>
);
}
export default Inhook;

我从json中得到了记录的数据,它有name、id、managerId和salary等等。当我在类组件中做这件事时,它得到了输出,在函数中或在jsx中钩子val((函数调用无穷多次,得到了这样的错误:(错误:重新渲染太多。React限制了渲染次数以防止无限循环。(

e.managerId === s.id为true的情况下,通过调用val(s.id)来更改渲染内部的状态。然后,当它们相等时,组件试图渲染val(s.id)时,其函数体(val(e)(中的一组状态发生变化,并且组件开始无限次地再次渲染。

试着看看是否可以通过引入一些setter来分离val(e)中的关注点,也许每个setter都有一个单独的函数。此外,计算要在渲染外的"true"p-tag(代替<p> {val(s.id)}</p>(中显示的值,然后将其传递给jsx!

您需要删除此行setRecords(props.records),因为它会导致每次渲染时的状态发生变化,这就是您拥有的无限循环
此外,你不需要这行const [records, setRecords] = useState([]);,你只需要显示道具中的记录,这里不需要本地状态。

此外,一些建议:

  • 您似乎正在尝试同时构建和显示员工树,这非常困难,您应该在显示之前构建需要显示的数据。要从数组构建树,请查看以下stackoverflow答案

看起来是这样的:


function Inhook(props) {
const initialState = 0;
const records = props.records
const sortedRecords = records.sort((x, y) => (x.empName.toLowerCase() > y.empName.toLowerCase()) * 2 - 1)
const employeeTree = createEmployeeTree(sortedRecords)
return (
<div>
<React.Fragment>
<br />
<div className="Tree">
<h1 style={{ textAlign: 'center' }}>Employee Tree</h1>
<h3>Test Case 1</h3>
<h4>Employee Tree</h4>
{employeeTree.map(manager => {
return (
<ul key={manager.id}>
<li style={{ fontWeight: 'bold' }}>
<p>
Employees of :
{manager.empName.toLowerCase()}
</p>
<ul>
{manager.children.map(employee => (
<li type="square" key={employee.id}>
{employee.empName.toLowerCase()}
{employee.children.map(e => (
<div>
<li
key={e.id}
type="disc"
style={{
marginLeft:
'120px',
}}>
{e.empName.toLowerCase()}
</li>
</div>
))}
</li>
))}
</ul>
</li>
</ul>
);
})}
</div>
</React.Fragment>
</div>
);
}
// Convert flat array to tree, see https://stackoverflow.com/a/40732240/6695569
const createEmployeeTree = data => {
let hashTable = {};
data.forEach(
aData => (hashTable[aData.id] = { ...aData, children: [] })
);
let dataTree = [];
data.forEach(aData => {
if (aData.managerId) {
if (!hashTable[aData.managerId]) return;
hashTable[aData.managerId].children.push(hashTable[aData.id]);
} else dataTree.push(hashTable[aData.id]);
});
return dataTree;
};
  • 另一个建议是,不要对派生值使用本地状态,例如,当count大于0时,您的show状态设置为true。那么您应该只使用计算值const show = count >0
// instead of this
const [count, setCount] = useState(initialState);
const [show, setShow] = useState(false);
function(){
setCount(0)
setShow(false)
...
if(count > 0) setShow(true)
else setShow(false)
}
//do This
const [count, setCount] = useState(initialState);
const show = count > 0
  • 另一个建议是,JSX很容易分割成组件,所以要这样做,不要制作很长的渲染图,因为它可能很难阅读,你可以这样分割:
function Inhook(props) {
return (
<div>
<Title />
<Managers employeeTree={employeeTree} />
</div>
)
}
function Title(){
return <h1 style={{ textAlign: 'center' }}>Employee Tree</h1>
}

function Managers({ employeeTree }) {
return (
<ul>
{employeeTree.map(manager => (
<li style={{ fontWeight: 'bold' }}>
<p>Employees of :{manager.empName.toLowerCase()}</p>
<Employees employees={manager.children} />
</li>
))}
</ul>
);
}
function Employees({ employees }) {
return (
<ul>
{employees.map(employee => (
<li type="square" key={employee.id}>
{employee.empName.toLowerCase()}
{employee.children.map(e => (
<div>
<li
key={e.id}
type="disc"
style={{
marginLeft: '120px',
}}>
{e.empName.toLowerCase()}
</li>
</div>
))}
</li>
))}
</ul>
);
}

最新更新