[英]Input Loses Focus Beacuse Of Re-Render, How to Make My Function On Top-Level With Pointers - React
Hi i have a function that dynamically creates parent-child components based on their ID and Parent ID, which worked fine until i added onChange
to the inputs, now they lose focus because of the re-rendering of their parent.嗨,我有一个 function,它根据它们的 ID 和父 ID 动态创建父子组件,在我将
onChange
添加到输入之前,它工作正常,现在由于重新渲染它们的父级,它们失去了焦点。
I know i need to make it top-level function but i dont seem to get how to pass the components and functions along.我知道我需要使它成为顶级 function 但我似乎不知道如何传递组件和功能。
Heres the code:继承人的代码:
const createItemsFromTree = (fromTree) => {
return (
<>
{fromTree.children?.length ? (
<>
<CustomTreeItem
className={`json-display ${fromTree.placeholder}`}
key={fromTree.id}
label={
<div className="flex items-center gap-1 border border-[#e0dbdb] rounded-lg px-2 min-h-[36px] w-full my-[5px]">
<input
type="text"
className="outline-none text-[12px] w-full"
placeholder={
fromTree.parentId ? "Sub-Category" : "Category"
}
value={fromTree.name && fromTree.name}
onChange={(e) =>
handleCategoryInputChange(fromTree.id, e.target.value)
}
/>
{!fromTree.firstCategory && (
<Button
icon={<FaTimes color="#adadad" size={14} />}
title={!fromTree.parentId ? "" : ""}
onClick={() => handleRemovecategory(fromTree.id)}
customClasses={`w-fit text-[10px] p-0 m-0 mx-0 mr-0 py-0 px-0 bg-transparent `}
/>
)}
<Button
icon={<AiOutlinePlusSquare color="#bcbcbc" size={20} />}
title={!fromTree.parentId ? "" : ""}
containerClass="float-right"
onClick={() => handleAddSubCategory(fromTree.id)}
customClasses={`w-fit text-[10px] p-0 m-0 mx-0 mr-0 py-0 px-0 bg-transparent absolute translate-x-[12px] ${
!fromTree.children?.length ? "mr-[30px]" : ""
}`}
/>
</div>
}
nodeId={fromTree.id}
defaultExpanded={[fromTree.id, fromTree.parentId]}
onClick={() => console.log(fromTree)}
>
{fromTree.children.length > 0 &&
fromTree.children.map((child) => createItemsFromTree(child))}
</CustomTreeItem>
</>
) : (
<>
<CustomTreeItem
className={`json-display ${fromTree.placeholder}`}
key={fromTree.id}
label={
<div
className={`flex items-center gap-1 border border-[#e0dbdb] rounded-lg px-2 min-h-[36px] w-full ${
fromTree.children.length || !fromTree.parentId
? ""
: "ml-[20px]"
} my-[5px]`}
>
<input
type="text"
className="outline-none text-[12px] w-full"
placeholder={
fromTree.parentId ? "Sub-Category" : "Category"
}
value={fromTree.name && fromTree.name}
onChange={(e) =>
handleCategoryInputChange(fromTree.id, e.target.value)
}
/>
{!fromTree.firstCategory && (
<Button
icon={<FaTimes color="#adadad" size={14} />}
title={!fromTree.parentId ? "" : ""}
onClick={() => handleRemovecategory(fromTree.id)}
customClasses={`w-fit text-[10px] p-0 m-0 mx-0 mr-0 py-0 px-0 bg-transparent `}
/>
)}
</div>
}
nodeId={fromTree.id}
defaultExpanded={[fromTree.id, fromTree.parentId]}
onClick={() => console.log(fromTree)}
/>
<Button
icon={<AiOutlinePlusSquare color="#bcbcbc" size={20} />}
title={!fromTree.parentId ? "" : ""}
containerClass="float-right"
onClick={() => handleAddSubCategory(fromTree.id)}
customClasses={`w-fit text-[10px] p-0 m-0 mx-0 mr-0 py-0 px-0 bg-transparent translate-y-[-23px] translate-x-[3px] absolute ${
!fromTree.children?.length ? "mr-[30px]" : ""
}`}
/>
</>
)}
</>
);
};
Then in the jsx i call it like this:然后在 jsx 中我这样称呼它:
<TreeView
aria-label="file system navigator"
expanded={expanded}
onNodeToggle={handleToggle}
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
sx={{
height: 240,
flexGrow: 1,
maxWidth: 400,
overflowY: "auto",
}}
>
{categories?.map((category) => createItemsFromTree(category))}
</TreeView>
If you need more information i can provide freely.如果您需要更多信息,我可以免费提供。
Use a top level component for that:为此使用顶级组件:
const CategoryTree = ({ category }) => {
return (
<>
{fromTree.children?.length ? (
<>
<CustomTreeItem
className={`json-display ${fromTree.placeholder}`}
key={fromTree.id}
label={
<div className="flex items-center gap-1 border border-[#e0dbdb] rounded-lg px-2 min-h-[36px] w-full my-[5px]">
<input
type="text"
className="outline-none text-[12px] w-full"
placeholder={
category.parentId ? "Sub-Category" : "Category"
}
value={fromTree.name && fromTree.name}
onChange={(e) =>
handleCategoryInputChange(fromTree.id, e.target.value)
}
/>
{!fromTree.firstCategory && (
<Button
icon={<FaTimes color="#adadad" size={14} />}
title={!fromTree.parentId ? "" : ""}
onClick={() => handleRemovecategory(fromTree.id)}
customClasses={`w-fit text-[10px] p-0 m-0 mx-0 mr-0 py-0 px-0 bg-transparent `}
/>
)}
<Button
icon={<AiOutlinePlusSquare color="#bcbcbc" size={20} />}
title={!fromTree.parentId ? "" : ""}
containerClass="float-right"
onClick={() => handleAddSubCategory(category.id)}
customClasses={`w-fit text-[10px] p-0 m-0 mx-0 mr-0 py-0 px-0 bg-transparent absolute translate-x-[12px] ${
!category.children?.length ? "mr-[30px]" : ""
}`}
/>
</div>
}
nodeId={fromTree.id}
defaultExpanded={[fromTree.id, fromTree.parentId]}
onClick={() => console.log(fromTree)}
>
{fromTree.children.length > 0 &&
fromTree.children.map((child) => createItemsFromTree(child))}
</CustomTreeItem>
</>
) : (
<>
<CustomTreeItem
className={`json-display ${fromTree.placeholder}`}
key={fromTree.id}
label={
<div
className={`flex items-center gap-1 border border-[#e0dbdb] rounded-lg px-2 min-h-[36px] w-full ${
fromTree.children.length || !fromTree.parentId
? ""
: "ml-[20px]"
} my-[5px]`}
>
<input
type="text"
className="outline-none text-[12px] w-full"
placeholder={
category.parentId ? "Sub-Category" : "Category"
}
value={fromTree.name && fromTree.name}
onChange={(e) =>
handleCategoryInputChange(fromTree.id, e.target.value)
}
/>
{!fromTree.firstCategory && (
<Button
icon={<FaTimes color="#adadad" size={14} />}
title={!fromTree.parentId ? "" : ""}
onClick={() => handleRemovecategory(fromTree.id)}
customClasses={`w-fit text-[10px] p-0 m-0 mx-0 mr-0 py-0 px-0 bg-transparent `}
/>
)}
</div>
}
nodeId={fromTree.id}
defaultExpanded={[fromTree.id, fromTree.parentId]}
onClick={() => console.log(fromTree)}
/>
<Button
icon={<AiOutlinePlusSquare color="#bcbcbc" size={20} />}
title={!fromTree.parentId ? "" : ""}
containerClass="float-right"
onClick={() => handleAddSubCategory(category.id)}
customClasses={`w-fit text-[10px] p-0 m-0 mx-0 mr-0 py-0 px-0 bg-transparent translate-y-[-23px] translate-x-[3px] absolute ${
!category.children?.length ? "mr-[30px]" : ""
}`}
/>
</>
)}
</>
);
};
In your JSX, and pass down the property you need to pass.在你的 JSX 中,传递你需要传递的属性。
{categories?.map((category) => <TreeForCategory category={category} />}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.