我正在使用 React Native 中的筆記串列,當我處于“編輯模式”時,我使用了一種性能不佳的方法來選擇/取消選擇筆記。每次我選擇一個筆記時,應用程式每次都必須重新渲染整個串列。如果我用 100 個音符進行測驗,很明顯,當我選擇/取消選擇一個音符時會出現輸入滯后。
所以我決定將“選擇狀態”移動到單個子組件。通過這樣做,我只在那個組件上重新渲染,所以這是一個巨大的性能改進。到這里為止,一切正常。
問題是當我禁用編輯模式時。例如,如果我選擇 3 個音符,并禁用“編輯模式”,則這些音符將保持選中狀態(事實上,該風格也將保持不變)。我想重置所有選定筆記的狀態,或者找到一個有效的替代方案。
我在 CodeSandbox 上使用 React(不是 React Native)與父母和孩子一起重新創建了場景:https ://codesandbox.io/s/loving-field-bh0k9k
行為完全相同。我希望你能幫助我。謝謝。
tl;博士:
用例:
- 通過選擇 0.5 秒的音符進入編輯模式
- 通過單擊選擇 2/3 元素
- 通過選擇 0.5 秒的音符來禁用編輯模式
期望:所有元素都被取消選擇(孩子的狀態被重置)
現實:元素不會被取消選擇(孩子的狀態保持不變)
uj5u.com熱心網友回復:
這很容易用useEffect鉤子完成。它允許您“觀察”變數隨時間的變化。
當editMode更改效果掛鉤的內容時運行,因此當editMode從true到時false,它將設定專案的selected狀態。
將此添加到您的<Child />組件中:
useEffect(() => {
if (!editMode) {
setSelected(false);
}
}, [editMode]);
uj5u.com熱心網友回復:
如果你使用React.memo,你可以快取子組件并防止它們重新渲染。
const Parent = () => {
const [editMode, setEditMode] = useState(false);
const [childrenList, setChildrenList] = useState(INITIAL_LIST);
const [selected, setSelected] = useState([]);
const toggleEditMode = useCallback(() => {
if (editMode) {
setSelected([]);
}
setEditMode(!editMode);
}, [editMode]);
const deleteSelectedChildren = () => {
setChildrenList(childrenList.filter((x) => !selected.includes(x.id)));
setEditMode(false);
};
const onSelect = useCallback((id) => {
setSelected((prev) => {
if (prev.includes(id)) {
return prev.filter((x) => x !== id);
}
return [...prev, id];
});
}, []);
// Check when <Parent /> is re-rendered
console.log("Parent");
return (
<>
<h1>Long press an element to enable "Edit Mode"</h1>
<ul className="childrenWrapper">
{childrenList.map((content, index) => (
<Child
key={content.id}
index={index}
content={content}
editMode={editMode}
toggleEditMode={toggleEditMode}
onSelect={onSelect}
selected={selected.includes(content.id)}
/>
))}
</ul>
{editMode && (
<button onClick={deleteSelectedChildren}>DELETE SELECTED</button>
)}
</>
);
};
您必須將作為道具傳遞的函式包裝在內部useCallback,否則它們在每個 Parent 渲染上都會有所不同,從而使記憶無效。
import { useRef, memo } from "react";
const Child = memo(
({ content, editMode, toggleEditMode, onSelect, selected }) => {
// Prevent re-rendering when setting timer thread
const timerRef = useRef();
// Toggle selection of the <Child /> and update selectedChildrenIndexes
const toggleCheckbox = () => {
if (!editMode) return;
onSelect(content.id);
};
// Toggle Edit mode after .5s of holding press on a Child component
const longPressStartHandler = () => {
timerRef.current = setTimeout(toggleEditMode, 500);
};
// Release setTimeout thread in case it's pressed less than .5s
const longPressReleaseHandler = () => {
clearTimeout(timerRef.current);
};
// Check when <Child /> is re-rendered
console.log("Child - " content.id);
return (
<li
className={`childContent ${editMode && "editMode"} ${
selected && "selected"
}`}
onMouseDown={longPressStartHandler}
onMouseUp={longPressReleaseHandler}
onClick={toggleCheckbox}
>
<pre>
<code>{JSON.stringify(content)}</code>
</pre>
{editMode && (
<input type="checkbox" onChange={toggleCheckbox} checked={selected} />
)}
</li>
);
}
);
您可以在此處查看一個作業示例。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/524187.html
標籤:反应反应式表现状态
下一篇:Julia:隨機多項式分配
