reactjs - 更新大列表的一个元素而不在反应钩子中重新渲染其他元素?
问题描述
我想通过测试li
一个简单的待办事项列表的大列表来优化我的反应应用程序。
例如,当点击 a 时li
,任务将被直通,并且检查图标将变为绿色。这个简单的动作对于一个大列表来说非常慢,因为整个列表都是重新渲染的。
如何使用 React Hooks 做到这一点?
function App() {
const [list, setList] = useState([]);
const [input, setInput] = useState("");
const inputRef = useRef(null);
useEffect(() => inputRef.current.focus(), []);
//Pseudo Big List
useEffect(() => {
const test = [];
let done = false;
for (let i = 0; i < 5000; i++) {
test.push({ task: i, done });
done = !done;
}
setList(test);
}, []);
const handlerSubmit = (e) => {
e.preventDefault();
const newTask = { task: input, done: false };
const copy = [...list, newTask];
setList(copy);
setInput("");
};
const checkHandler = (e, index) => {
e.stopPropagation();
const copy = [...list];
copy[index].done = !copy[index].done;
setList(copy);
};
const suppression = (e, index) => {
e.stopPropagation();
const copy = [...list];
copy.splice(index, 1);
setList(copy);
};
const DisplayList = () => {
return (
<ul>
{list.map((task, index) => (
<Li
key={index}
task={task}
index={index}
suppression={suppression}
checkHandler={checkHandler}
/>
))}
</ul>
);
};
//JSX
return (
<div className='App'>
<h1>TODO JS-REACT</h1>
<form id='form' onSubmit={handlerSubmit}>
<input
type='text'
placeholder='Add task'
required
onChange={(e) => setInput(e.target.value)}
value={input}
ref={inputRef}
/>
<button type='submit'>
<i className='fas fa-plus'></i>
</button>
</form>
{list.length === 0 && <div id='noTask'>No tasks...</div>}
<DisplayList />
</div>
);
}
export default App;
锂成分
import React from "react";
export default function Li(props) {
return (
<li
onClick={(e) => props.checkHandler(e, props.index)}
className={props.task.done ? "line-through" : undefined}
>
{props.task.task}
<span className='actions'>
<i className={`fas fa-check-circle ${props.task.done && "green"}`}></i>
<i
className='fas fa-times'
onClick={(e) => props.suppression(e, props.index)}
></i>
</span>
</li>
);
}
这里的代码沙盒: https ://codesandbox.io/s/sad-babbage-kp3md ?file=/src/App.js
解决方案
您可以使用React.memo
和包装Li
组件。Li
这将基于浅比较缓存组件的实例。在文档中阅读更多内容
否则,如果您不需要容器中的状态,您可以将其本地保存在Li
组件中,这样就不会导致整个列表重新渲染。
推荐阅读
- php - Alexa SMAPI - 更新意图返回错误:“指定的技能或区域设置没有关联的模型。”
- angularjs - 我们可以在单击饼图图例标签时删除条形图线吗?
- html - 为什么我的 .png 网站徽标文件不会显示在我的网站上?
- php - 如何在字符串中添加新行?
- spring - Spring Security:会话有效时禁用登录页面
- linux - 为什么子进程会调用 getppid()?Parent 的 PID 可以用来做什么?
- javascript - 如何从 HTML 字符串生成动态 HTML?
- java - 如何在 jtextfield 上迭代和打印矩阵?
- flutter-layout - 如何对齐行首的第一项和行尾的第二项?
- java - 类型不匹配:无法使用 java 在 selenium webdriver 中从 ChromeDriver 转换为 WebDriver