【发布时间】:2023-03-22 09:48:02
【问题描述】:
我希望用户能够对待办事项列表进行排序。当用户从下拉列表中选择一个项目时,它将设置sortKey,这将创建一个新版本的setSortedTodos,然后触发useEffect并调用setSortedTodos。
下面的例子完全符合我的要求,但是 eslint 提示我将 todos 添加到 useEffect 依赖数组,如果我这样做会导致无限循环(如您所料)。
const [todos, setTodos] = useState([]);
const [sortKey, setSortKey] = useState('title');
const setSortedTodos = useCallback((data) => {
const cloned = data.slice(0);
const sorted = cloned.sort((a, b) => {
const v1 = a[sortKey].toLowerCase();
const v2 = b[sortKey].toLowerCase();
if (v1 < v2) {
return -1;
}
if (v1 > v2) {
return 1;
}
return 0;
});
setTodos(sorted);
}, [sortKey]);
useEffect(() => {
setSortedTodos(todos);
}, [setSortedTodos]);
现场示例:
const {useState, useCallback, useEffect} = React;
const exampleToDos = [
{title: "This", priority: "1 - high", text: "Do this"},
{title: "That", priority: "1 - high", text: "Do that"},
{title: "The Other", priority: "2 - medium", text: "Do the other"},
];
function Example() {
const [todos, setTodos] = useState(exampleToDos);
const [sortKey, setSortKey] = useState('title');
const setSortedTodos = useCallback((data) => {
const cloned = data.slice(0);
const sorted = cloned.sort((a, b) => {
const v1 = a[sortKey].toLowerCase();
const v2 = b[sortKey].toLowerCase();
if (v1 < v2) {
return -1;
}
if (v1 > v2) {
return 1;
}
return 0;
});
setTodos(sorted);
}, [sortKey]);
useEffect(() => {
setSortedTodos(todos);
}, [setSortedTodos]);
const sortByChange = useCallback(e => {
setSortKey(e.target.value);
});
return (
<div>
Sort by:
<select onChange={sortByChange}>
<option selected={sortKey === "title"} value="title">Title</option>
<option selected={sortKey === "priority"} value="priority">Priority</option>
</select>
{todos.map(({text, title, priority}) => (
<div className="todo">
<h4>{title} <span className="priority">{priority}</span></h4>
<div>{text}</div>
</div>
))}
</div>
);
}
ReactDOM.render(<Example />, document.getElementById("root"));
body {
font-family: sans-serif;
}
.todo {
border: 1px solid #eee;
padding: 2px;
margin: 4px;
}
.todo h4 {
margin: 2px;
}
.priority {
float: right;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.2/umd/react-dom.production.min.js"></script>
我认为必须有更好的方法来让 eslint 开心。
【问题讨论】:
-
附带说明:
sort回调可以是:return a[sortKey].toLowerCase().localeCompare(b[sortKey].toLowerCase());,如果环境具有合理的区域信息,它还具有进行区域比较的优势。如果你愿意,你也可以对它进行解构:pastebin.com/7X4M1XTH -
eslint抛出什么错误? -
您能否使用 Stack Snippets(
[<>]工具栏按钮)更新问题以提供问题的可运行 minimal reproducible example? Stack Snippets 支持 React,包括 JSX; here's how to do one。这样人们就可以检查他们提出的解决方案是否存在无限循环问题...... -
这是一个非常有趣的方法,也是一个非常有趣的问题。正如您所说,您可以理解为什么 ESLint 认为您需要将
todos添加到useEffect上的依赖数组中,并且您可以看到为什么不应该这样做。 :-) -
我为您添加了实时示例。真的很想看到这个答案。
标签: javascript reactjs react-hooks eslint